aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/pre/include
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-07-24 16:35:34 +0000
committerFelix Morgner <felix.morgner@ost.ch>2025-07-24 16:35:34 +0000
commit2d3399ab6072acd85811a54fce8eff50628888b6 (patch)
treebb6f63b58861938c6e15492732b440459dd22d62 /arch/x86_64/pre/include
parent1b65136a11453fe7e89320dfe6170a0cd75e60dd (diff)
downloadkernel-2d3399ab6072acd85811a54fce8eff50628888b6.tar.xz
kernel-2d3399ab6072acd85811a54fce8eff50628888b6.zip
x86_64: move files out of the way
Diffstat (limited to 'arch/x86_64/pre/include')
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp69
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp81
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp24
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp40
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp45
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp105
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/main.hpp51
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp104
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp93
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp37
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp41
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp73
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp74
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp32
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp88
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp18
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp18
-rw-r--r--arch/x86_64/pre/include/arch/exception_handling/assert.hpp17
-rw-r--r--arch/x86_64/pre/include/arch/exception_handling/panic.hpp23
-rw-r--r--arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp34
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/call.hpp30
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/if.hpp21
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp64
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp97
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp24
-rw-r--r--arch/x86_64/pre/include/arch/kernel/halt.hpp13
-rw-r--r--arch/x86_64/pre/include/arch/kernel/main.hpp13
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp67
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/concept.hpp21
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp74
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/bump_allocator.hpp48
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/global_heap_allocator.hpp118
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/heap_allocator.hpp45
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/linked_list_allocator.hpp120
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/memory_block.hpp39
-rw-r--r--arch/x86_64/pre/include/arch/memory/heap/user_heap_allocator.hpp149
-rw-r--r--arch/x86_64/pre/include/arch/memory/main.hpp30
-rw-r--r--arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp170
-rw-r--r--arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp58
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp206
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp39
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp180
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp121
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/page_table.hpp157
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp64
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp91
-rw-r--r--arch/x86_64/pre/include/arch/user/main.hpp16
50 files changed, 3223 insertions, 0 deletions
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
new file mode 100644
index 0000000..07110c8
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
@@ -0,0 +1,69 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp"
+#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp"
+#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ __extension__ typedef __int128 int128_t;
+ __extension__ typedef unsigned __int128 uint128_t;
+
+ /**
+ * @brief Defines helper function for all states and the actual data the gate descriptor can have.
+ */
+ struct [[gnu::packed]] gate_descriptor
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ gate_descriptor() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @note Created gate descriptor copies the given bytes into these components ending with a 32 bit reserved
+ * field that has to be used, because the 64-bit gate descriptor needs to be big enough for two 32-bit gate
+ * descriptor.
+ * - 16 bit Segment Selector
+ * - 3 bit Interrupt Stack Table Offset
+ * - 8 bit Type and Flags
+ * - 64 bit Offset
+ *
+ * @param flags Copies the bits set from the given data into the individual components of a gate
+ * descriptor.
+ */
+ explicit gate_descriptor(uint128_t flags);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param selector, ist, flags, offset Copies the bits set from the given data into the individual components of
+ * a gate descriptor.
+ */
+ gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset);
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(gate_descriptor const & other) const -> bool = default;
+
+ private:
+ // The order in private variables starts for the first variable being the rightmost bit.
+ uint16_t _offset_1 = {}; ///< Lower 16 bits of handler function address (0 - 15)
+ segment_selector _selector = {}; ///< Segment selector (16 - 31)
+ ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39)
+ idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47)
+ uint64_t _offset_2 : 48 = {}; ///< Upper 48 bits of handler function address (48 - 95)
+ uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127)
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
new file mode 100644
index 0000000..5104c36
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
@@ -0,0 +1,81 @@
+
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the access byte field of a segment descriptor can
+ * have.
+ */
+ struct [[gnu::packed]] idt_flags
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ INTERRUPT_GATE = 0b01110, ///< The actual type of gate segment is a interrupt gate.
+ TRAP_GATE = 0b01111, ///< The actual type of gate segment is a trap gate.
+ DESCRIPTOR_LEVEL_KERNEL =
+ 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources.
+ DESCRIPTOR_LEVEL_ADMIN =
+ 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_PRIVILEGED_USER =
+ 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory.
+ PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment.
+ ///< Must be set (1) for any valid segment.
+ };
+
+ /**
+ * @brief Default Constructor.
+ */
+ idt_flags() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used
+ * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags
+ * are enabled or not using contains_flags method.
+ */
+ idt_flags(uint8_t flags);
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<8U> other) const -> bool;
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(idt_flags const & other) const -> bool = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<8U> other) -> void;
+
+ private:
+ uint8_t _flags = {}; ///< Underlying bits used to read the flags from.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
new file mode 100644
index 0000000..b388e0e
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
@@ -0,0 +1,24 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Updates the IDTR with the created interrupt descriptor table. If it has not been created yet this
+ * method will create it.
+ */
+ auto update_interrupt_descriptor_table_register() -> void;
+
+ /**
+ * @brief Creates the interrupt descriptor table, with the minimum required configuration. If this method is called
+ * more than once, the previously created instance is returned instead.
+ *
+ * @return Reference to the created interrupt_descriptor_table.
+ */
+ auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table &;
+
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
new file mode 100644
index 0000000..7fe933b
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
@@ -0,0 +1,40 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp"
+#include "arch/stl/vector.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ using interrupt_descriptor_table = stl::vector<gate_descriptor>;
+
+ /**
+ * @brief Represents a pointer to the Interrupt Descriptor Table (IDT).
+ *
+ * This structure is used to store the base address and length of the IDT.
+ */
+ struct [[gnu::packed]] interrupt_descriptor_table_pointer
+ {
+ /**
+ * @brief Default constructor.
+ */
+ interrupt_descriptor_table_pointer() = default;
+
+ /**
+ * @brief Constructor.
+ */
+ interrupt_descriptor_table_pointer(uint16_t table_length, gate_descriptor * address);
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default;
+
+ private:
+ uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1.
+ gate_descriptor * address = {}; ///< Non-owning pointer to the IDT base address.
+ };
+
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
new file mode 100644
index 0000000..e45bcf4
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
@@ -0,0 +1,45 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the interrupt stack table offset field of a gate descriptor can
+ * have. Is automatically increased to one byte in size, to include the following 5 reserved bits in the gate
+ * descriptor.
+ */
+ struct [[gnu::packed]] ist_offset
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ ist_offset() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param offset Offset into the interrupt stack table. A value of of 0 means we do not switch stacks, whereas 1 - 7
+ * mean we switch to the n-th stack in the Interrupt Stack Table, contained in the TSS if the gate descriptor that
+ * contains this field is called.
+ */
+ ist_offset(uint8_t offset);
+
+ /**
+ * @brief Allows to compare the underlying set bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(ist_offset const & other) const -> bool = default;
+
+ private:
+ uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 means we do not switch stacks,
+ ///< whereas 1 - 7 mean we switch to the n-th stack in the Interrupt Stack Table, contained
+ ///< in the TSS if the gate descriptor that contains this field is called.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
new file mode 100644
index 0000000..2a7704e
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
@@ -0,0 +1,105 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Represents a segment selector in the x86_64 architecture, which points to a valid code segment in the global
+ * descriptor table.
+ *
+ * A segment selector is a 16-bit identifier used to select a segment descriptor
+ * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT).
+ * It contains an index, a table indicator (TI), and a requested privilege level (RPL).
+ */
+ struct [[gnu::packed]] segment_selector
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ REQUEST_LEVEL_KERNEL =
+ 0U << 0U, ///< Highest privileged level used by the kernel to allow for full access of resources.
+ REQUEST_LEVEL_ADMIN =
+ 1U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ REQUEST_LEVEL_PRIVILEGED_USER =
+ 2U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ REQUEST_LEVEL_USER = 3U << 0U, ///< Restricts access to only application and their specific memory.
+ LOCAL_DESCRIPTOR_TABLE = 1U << 2U, ///< Wheter the index referes to an entry in the local or global descriptor
+ ///< table. If enabled the index points to a local descriptor table, if it is
+ ///< cleared it referes to a global descriptor table instead.
+ };
+
+ /**
+ * @brief Default constructor.
+ */
+ segment_selector() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param index Index into the local or global descriptor table. Processor multiplies the index value by 8 (number
+ * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT address.
+ * @param flags Allows to set flags for the flags field using the unscoped enum contained in this class, used to
+ * allow for direct integer conversion.
+ */
+ constexpr segment_selector(uint16_t index, uint8_t flags)
+ : _flags(flags)
+ , _index(index)
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<3U> other) const -> bool;
+
+ /**
+ * @brief Gets the index into the global descriptor table or the local descriptor table this segment selector is
+ * pointing too.
+ *
+ * @return Underlying value of the index field, bit 3 - 16.
+ */
+ [[gnu::section(".user_text")]]
+ auto get_index() const -> uint16_t;
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(segment_selector const & other) const -> std::strong_ordering = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<3U> other) -> void;
+
+ /**
+ * @brief Cast the underlying data into a combined 16-bit form, that contains all data.
+ *
+ * @return Underlying value combined into it's full size.
+ */
+ operator uint16_t() const;
+
+ private:
+ uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from.
+ uint16_t _index : 13 =
+ {}; ///< Index into the local or global descriptor table. Processor multiplies the index value by 16 (number of
+ ///< bytes in segment descriptor) and adds the result to the base address.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/main.hpp b/arch/x86_64/pre/include/arch/context_switching/main.hpp
new file mode 100644
index 0000000..f8477ea
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/main.hpp
@@ -0,0 +1,51 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp"
+#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp"
+
+namespace teachos::arch::context_switching
+{
+ /**
+ * @brief Contains the references to the tables required for context switching
+ */
+ struct descriptor_tables
+ {
+ segment_descriptor_table::global_descriptor_table & gdt; ///< Reference to the global descriptor table.
+ interrupt_descriptor_table::interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table.
+ };
+
+ /**
+ * @brief Creates the Interrupt Descriptor Table and Global Descriptor Table as a static variable the first time this
+ * method is called and update IDTR and GDTR registers values.
+ *
+ * @note Subsequent calls after the first one, will simply return the previously created tables, but not update the
+ * registers again.
+ *
+ * @return References to the statically created Interrupt Descriptor and Global Descriptor Table.
+ */
+ auto initialize_descriptor_tables() -> descriptor_tables;
+
+ /**
+ * @brief Switches from the current Kernel Mode (Level 0) to User Mode (Level 3). Will simply use predefined Segment
+ * Selectors for the User Data and User Code Segment, which are Index 3 and 4 in the GDT respectively.
+ */
+ auto switch_to_user_mode() -> void;
+
+ /**
+ * @brief Switches from the current Code and Data Segment to the given Code and Data Segment.
+ *
+ * @note This method will additionally call initialize_descriptor_tables, to ensure the GDTR and IDTR have been setup
+ * correctly before attempting to switch the context. This switch is achieved using a far return, which will once
+ * executed call the given void function.
+ *
+ * @param data_segment Data Segment that the SS, DS; ES, FS and GS register will be set too.
+ * @param code_segment Code Segment that the CS register will be set too.
+ * @param return_function Function that will be called once the switch has been achieved.
+ */
+ auto switch_context(interrupt_descriptor_table::segment_selector data_segment,
+ interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void;
+
+} // namespace teachos::arch::context_switching
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
new file mode 100644
index 0000000..7450330
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
@@ -0,0 +1,104 @@
+
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the access byte field of a segment descriptor can
+ * have.
+ */
+ struct [[gnu::packed]] access_byte
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ ACCESSED =
+ 1U
+ << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the
+ ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear.
+ WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows
+ ///< read and write access, otherwise only read access is possible.
+ READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows
+ ///< read and execute access, otherwise only executable access is possible.
+ CONFORMING =
+ 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels
+ ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise
+ ///< access from different privilege levels with throw a General-Protectione exception.
+ EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the
+ ///< data segment expands downwards, otherwise it expands upwards.
+ CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code
+ ///< segment, otherwise its a data segment.
+ LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table.
+ TASK_STATE_SEGMENT_AVAILABLE =
+ 9, ///< The actual type of sytem segment is a task state segment that is still available.
+ TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in
+ ///< use and therefore busy.
+ CALL_GATE = 11, ///< The actual type of sytem segment is a call gate.
+ INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate.
+ TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate.
+ CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1).
+ DESCRIPTOR_LEVEL_KERNEL =
+ 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources.
+ DESCRIPTOR_LEVEL_ADMIN =
+ 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_PRIVILEGED_USER =
+ 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory.
+ PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment.
+ ///< Must be set (1) for any valid segment.
+ };
+
+ /**
+ * @brief Default Constructor.
+ */
+ access_byte() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used
+ * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags
+ * are enabled or not using contains_flags method.
+ */
+ access_byte(uint8_t flags);
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<8U> other) const -> bool;
+
+ /**
+ * @brief Allows to compare the underlying data of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying data of both types is the same.
+ */
+ auto operator==(access_byte const & other) const -> bool = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<8U> other) -> void;
+
+ private:
+ uint8_t _flags = {}; ///< Underlying bits used to read the flags from.
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp
new file mode 100644
index 0000000..e24b988
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp
@@ -0,0 +1,93 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP
+
+#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp"
+
+#include <bitset>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the flags field of a segment descriptor can
+ * have.
+ */
+ struct [[gnu::packed]] gdt_flags
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ LONG_MODE = 1U << 1U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment
+ ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions
+ ///< are executed in 64-bit code, otherwise they are executed in compatability 32-bit mode.
+ ///< If this bit is set the 3rd bit needs to be clear (0).
+ UPPER_BOUND = 1U << 2U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 4
+ ///< GiB, 4 KiB otherwise.
+ STACK_POINTER_SIZE = 1U << 2U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for
+ ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise.
+ DEFAULT_LENGTH = 1U << 2U, ///< Indicates the default length for code segments with effective addresses and
+ ///< operands. Enable for 32 bit, 16 bit otherwise.
+ GRANULARITY = 1U << 3U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte
+ ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set.
+ };
+
+ /**
+ * @brief Default Constructor.
+ */
+ gdt_flags() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param flags Allows to set flags for the flags field using the unscoped enum contained in this class, used to
+ * allow for direct integer conversion. This value is saved and can later be used to check whether certain flags are
+ * enabled or not using contains_flags method.
+ * @param limit Does not necessarily make sense in the gdt flags type, but because the flags alone are only 4 bit
+ * the type would still require the space for a complete bit. Therefore the 4 bit segment limit field before the
+ * flags field is included in this type to ensure we actually contain 8 bit of data.
+ */
+ gdt_flags(uint8_t flags, std::bitset<20U> limit);
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<4U> other) const -> bool;
+
+ /**
+ * @brief Get part of the segment limit that is saved in the gdt flags. This does not necessarily make sense in this
+ * object, but it has to be included here because a struct can not be smaller than a full byte. Therefore we include
+ * the 4 bit segment limit field so that it results in a compelte byte with the addtional 4 bit of gdt flags.
+ *
+ * @return 4-bit limit segment
+ */
+ auto get_limit() const -> std::bitset<4U>;
+
+ /**
+ * @brief Allows to compare the underlying set bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(gdt_flags const & other) const -> bool = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<4U> other) -> void;
+
+ private:
+ uint8_t _limit_2 : 4 = {}; ///< Second part of the limit field.
+ uint8_t _flags : 4 = {}; ///< Underlying bits used to read the flags from.
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp
new file mode 100644
index 0000000..44f2692
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp
@@ -0,0 +1,37 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP
+
+#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp"
+#include "arch/context_switching/segment_descriptor_table/task_state_segment.hpp"
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Creates the global descriptor table, with the minimum required configuration. If this method is called more
+ * than once, the previously created instance is returned instead.
+ *
+ * @return Reference to the created global_descriptor_table.
+ */
+ auto get_or_create_gdt() -> global_descriptor_table &;
+
+ /**
+ * @brief Updates the GDTR with the created global descriptor table. If it has not been created yet this
+ * method will create it.
+ *
+ * @note This method will only set the GDTR, but for the processor to actually register the change a far jump
+ * has to be executed. This also has to be done before updating the TR.
+ */
+ auto update_gdtr() -> void;
+
+ /**
+ * @brief Updates the TR with the created task state segment. If it has not been created yet this
+ * method will create it.
+ *
+ * @note This method should only be called after update_gdtr() and a far jump has been
+ * executed. Because before that trying to access the segment will cause an exception.
+ */
+ auto update_tss_register() -> void;
+
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp
new file mode 100644
index 0000000..292ff70
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp
@@ -0,0 +1,41 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP
+
+#include "arch/stl/vector.hpp"
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ using global_descriptor_table = stl::vector<uint64_t>;
+
+ /**
+ * @brief Represents a pointer to the Global Descriptor Table (GDT).
+ *
+ * This structure is used to store the base address and length of the GDT.
+ * It is used when loading or modifying the GDT during context switching.
+ */
+ struct [[gnu::packed]] global_descriptor_table_pointer
+ {
+ /**
+ * @brief Default constructor.
+ */
+ global_descriptor_table_pointer() = default;
+
+ /**
+ * @brief Constructor.
+ */
+ global_descriptor_table_pointer(uint16_t table_length, uint64_t * address);
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(global_descriptor_table_pointer const & other) const -> std::strong_ordering = default;
+
+ private:
+ uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1.
+ uint64_t * address = {}; ///< Non-owning pointer to the GDT base address.
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp
new file mode 100644
index 0000000..933fb4d
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp
@@ -0,0 +1,73 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP
+
+#include "arch/context_switching/segment_descriptor_table/access_byte.hpp"
+#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp"
+#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp"
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states and the actual data the segment descriptor can have.
+ */
+ struct [[gnu::packed]] segment_descriptor_base
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ segment_descriptor_base() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @note Created segment descriptor copies the given bytes into these components requiring the space of one
+ * segment descriptor entry in the global descriptor table being 64-bit.
+ * - 8 bit Access Type
+ * - 4 bit Flags
+ * - 32 bit Base Address
+ * - 20 bit Limit
+ *
+ * @param flags Copies the bits set from the given data into the individual components of a segment
+ * descriptor.
+ */
+ explicit segment_descriptor_base(uint64_t flags);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of
+ * a segment descriptor.
+ */
+ segment_descriptor_base(access_byte access_byte, gdt_flags flags, uint32_t base, std::bitset<20U> limit);
+
+ /**
+ * @brief Calculates the underlying segment type that this segement descriptor is describing.
+ */
+ auto get_segment_type() const -> segment_descriptor_type;
+
+ /**
+ * @brief Cast the underlying data into a combined 64-bit form, that contains all data.
+ *
+ * @return Underlying value combined into it's full size.
+ */
+ operator uint64_t() const;
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(segment_descriptor_base const & other) const -> bool = default;
+
+ private:
+ // The order in private variables starts for the first variable being the rightmost bit.
+ uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15)
+ uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39)
+ access_byte _access = {}; ///< Access byte field (40 - 47)
+ gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55)
+ uint8_t _base_2 = {}; ///< Second part of the base field (56 - 63)
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp
new file mode 100644
index 0000000..40bcc8a
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp
@@ -0,0 +1,74 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP
+
+#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp"
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ __extension__ typedef __int128 int128_t;
+ __extension__ typedef unsigned __int128 uint128_t;
+
+ /**
+ * @brief Defines helper function for all states and the actual data the segment descriptor can have.
+ */
+ struct [[gnu::packed]] segment_descriptor_extension
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ segment_descriptor_extension() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @note Created segment descriptor copies the given bytes into these components requiring the space of two
+ * segment descriptor entry in the global descriptor table being 128-bit. Ending with a 32 bit reserved
+ * field that has to be used, because the segment descriptor needs to be big enough for two segment
+ * descriptor entries.
+ * - 8 bit Access Type
+ * - 4 bit Flags
+ * - 64 bit Base Address
+ * - 20 bit Limit
+ *
+ * @param flags Copies the bits set from the given data into the individual components of a segment
+ * descriptor.
+ */
+ explicit segment_descriptor_extension(uint128_t flags);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of
+ * a segment descriptor.
+ */
+ segment_descriptor_extension(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit);
+
+ /**
+ * @brief Returns the underlying base segment descriptor, being the first part of the segment descriptor consisting
+ * of two entries in the global descriptor table.
+ */
+ auto get_first_gdt_entry() const -> segment_descriptor_base;
+
+ /**
+ * @brief Returns the underlying extension to the segment descriptor, being the second part of the segment
+ * descriptor consiting of two entries in the global descriptor table.
+ */
+ auto get_second_gdt_entry() const -> uint64_t;
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(segment_descriptor_extension const & other) const -> bool = default;
+
+ private:
+ // The order in private variables starts for the first variable being the rightmost bit.
+ segment_descriptor_base _base = {}; ///< Base Segment Descriptor representing single entry in GDT (0 - 63)
+ uint32_t _base_3 = {}; ///< Third part of the base field (63 - 95)
+ uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127)
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp
new file mode 100644
index 0000000..8770b81
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp
@@ -0,0 +1,27 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Possible overlying types of the segment descriptor. Allowing to discern between the major types, which
+ * result in different handling of the actual data contained in the descriptor.
+ */
+ enum class segment_descriptor_type : uint8_t
+ {
+ SYSTEM_SEGMENT, ///< The segment is of type system, is distinguished by the Descriptor Type field in the Access
+ ///< Byte. Can be further distinguised to specific system segment types using the Type Field in the
+ ///< Access Byte.
+ DATA_SEGMENT, ///< The segment is of type data, is is distinguished by the Descriptor Type field in the Access
+ ///< Byte and the first bit of the Type Field in the Access Byte. Can be further distinguised to
+ ///< specific data segment types using the the remaining bits in the Type Field in the Access Byte.
+ CODE_SEGMENT, ///< The segment is of type code, is is distinguished by the Descriptor Type field in
+ ///< the Access Byte and the first bit of the Type Field in the Access Byte. Can be
+ ///< further distinguised to specific data segment types using the the remaining bits in
+ ///< the Type Field in the Access Byte.
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp
new file mode 100644
index 0000000..d4aa5e8
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp
@@ -0,0 +1,32 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief 64-bit task state segment
+ */
+ struct [[gnu::packed]] task_state_segment
+ {
+ private:
+ uint32_t : 32;
+ uint64_t rsp0 = {};
+ uint64_t rsp1 = {};
+ uint64_t rsp2 = {};
+ uint64_t : 64;
+ uint64_t ist1 = {};
+ uint64_t ist2 = {};
+ uint64_t ist3 = {};
+ uint64_t ist4 = {};
+ uint64_t ist5 = {};
+ uint64_t ist6 = {};
+ uint64_t ist7 = {};
+ uint64_t : 64;
+ uint16_t : 16;
+ uint16_t io_map_base_address = {};
+ };
+} // namespace teachos::arch::context_switching::segment_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp
new file mode 100644
index 0000000..59adc13
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp
@@ -0,0 +1,88 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching::syscall
+{
+ /**
+ * @brief Possible syscall implementation that should actually be called.
+ *
+ * @note Attempts to reflect the Linux interface partially. See https://filippo.io/linux-syscall-table/ for more
+ * information.
+ */
+ enum class type : uint64_t
+ {
+ WRITE = 1U, ///< Loads the arg_0 parameter as an address pointing to a const char array, which will then be printed
+ ///< onto the VGA buffer screen.
+ EXPAND_HEAP = 2U, /// Expands the User Heap by additonally mapping 100 KiB of virtual page memory. Ignores the
+ /// parameters and uses them as out parameters instead, where arg_0 is the start of the newly
+ /// mapped heap area and arg_1 is the size of the entire area. Can be less than 100 KiB if less
+ /// space remains.
+ ASSERT = 3U, /// Loads the arg_0 parameter as a boolean which needs to be true or it will print the message in
+ /// arg_1 parameter onto the VGA buffer screen, keep it as a nullptr if it shouldn't print anything
+ /// and then it halts the further execution of the application.
+ };
+
+ /**
+ * @brief Possible error codes that can be returned by the different syscall methods called depending on the type
+ * enum.
+ */
+ enum class error : uint8_t
+ {
+ OK = 0U, ///< No error occured in syscall.
+ OUT_OF_MEMORY = 1U, ///< Expanding heap failed because we have run out of mappable virtual address space.
+ };
+
+ /**
+ * @brief Allows to convert the error enum type into a boolean directly. Where any code besides 0 being no error, will
+ * return true. The remaining errors return true.
+ *
+ * @param e Error code that was returned by the syscall.
+ * @return Return true if there was no error and false otherwise.
+ */
+ constexpr bool operator!(error e) { return e == error::OK; }
+
+ /**
+ * @brief Maximum amount of arguments that can be passed to a syscall. Default value is 0 and arguments are only ever
+ * used depending on the actual enum type and if the method requires thoose parameters.
+ */
+ struct arguments
+ {
+ uint64_t arg_0{}; ///< First optional paramter to the syscall representing the RDI register.
+ uint64_t arg_1{}; ///< Second optional paramter to the syscall representing the RSI register.
+ uint64_t arg_2{}; ///< Third optional paramter to the syscall representing the RDX register.
+ uint64_t arg_3{}; ///< Fourth optional paramter to the syscall representing the R10 register.
+ uint64_t arg_4{}; ///< Fifth optional paramter to the syscall representing the R8 register.
+ uint64_t arg_5{}; ///< Sixth optional paramter to the syscall representing the R9 register.
+ };
+
+ /**
+ * @brief Response of a systemcall always containin an error code, signaling if the syscall even succeeded or not.
+ * Additionally it may contain up to 6 return values in the values struct.
+ */
+ struct response
+ {
+ error error_code; ///< Error code returned by the syscall. If it failed all the values will be 0.
+ arguments values = {}; ///< Optional return values of the syscall implementation.
+ };
+
+ /**
+ * @brief Calls the method associated with the given syscall number and passes the given optional arguments to it,
+ * over the RDI, RSI, RDX, R10, R8 and R9 register.
+ *
+ * @param syscall_number Syscall method that should be called. See enum values in type for possible implemented
+ * methods.
+ * @param args Optional arguments passable to the different syscall methods, called depending on the syscall_number.
+ * Not passing the required parameters to the method, will result in passing 0 instead, which might make the fail or
+ * not function correctly.
+ * @return The syscall implementation always returns a bool-convertable error code converting to true if the syscall
+ * failed or false if it didn't. Additionally it might pase additional values besides the error code, they will be set
+ * in the arguments struct. So the value can be read and used for further processing.
+ */
+ [[gnu::section(".user_text")]]
+ auto syscall(type syscall_number, arguments args = {}) -> response;
+
+} // namespace teachos::arch::context_switching::syscall
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp
new file mode 100644
index 0000000..8cb468a
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp
@@ -0,0 +1,18 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
+
+namespace teachos::arch::context_switching::syscall
+{
+ /**
+ * @brief Enables and sets up internal CPU registers to allow for syscall to function correctly and switch context
+ * temporarily back to the kernel level.
+ *
+ * @note Configures the Model Specific Register required by syscall (LSTAR, FMASK, STAR) with the correct values so
+ * that the syscall_handler is called and sets the System Call Extension bit on the EFER flags to allow for syscall
+ * to be used.
+ */
+ auto enable_syscall() -> void;
+
+} // namespace teachos::arch::context_switching::syscall
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp
new file mode 100644
index 0000000..2e7bcd1
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp
@@ -0,0 +1,18 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching::syscall
+{
+ /**
+ * @brief Handler for SYSCALL instruction. Calls a specific implementation based
+ * on the register RAX.
+ *
+ * @return Returns with LEAVE, SYSRETQ
+ */
+ auto syscall_handler() -> void;
+
+} // namespace teachos::arch::context_switching::syscall
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP
diff --git a/arch/x86_64/pre/include/arch/exception_handling/assert.hpp b/arch/x86_64/pre/include/arch/exception_handling/assert.hpp
new file mode 100644
index 0000000..1286768
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/exception_handling/assert.hpp
@@ -0,0 +1,17 @@
+#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP
+#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP
+
+namespace teachos::arch::exception_handling
+{
+ /**
+ * @brief Assert a condition to be true, if not do not continue
+ * execution of the code and print the given message to screen.
+ *
+ * @param condition Condition we want to be true or else halt execution.
+ * @param message Message that should be printed before halting the execution if the condition is not met.
+ */
+ auto assert(bool condition, char const * message) -> void;
+
+} // namespace teachos::arch::exception_handling
+
+#endif // TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP
diff --git a/arch/x86_64/pre/include/arch/exception_handling/panic.hpp b/arch/x86_64/pre/include/arch/exception_handling/panic.hpp
new file mode 100644
index 0000000..6a2404c
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/exception_handling/panic.hpp
@@ -0,0 +1,23 @@
+#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP
+#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP
+
+namespace teachos::arch::exception_handling
+{
+ /**
+ * @brief Print the given kernel panic message and then halt the system.
+ *
+ * @param reason Reason to print before halting the system.
+ */
+ [[noreturn]] auto panic(char const * reason) -> void;
+
+ /**
+ * @brief Print the given kernel panic message started by a given prefix and then halt the system.
+ *
+ * @param prefix Prefix to print before printing the reason.
+ * @param reason Reason to print before halting the system.
+ */
+ [[noreturn]] auto panic(char const * prefix, char const * reason) -> void;
+
+} // namespace teachos::arch::exception_handling
+
+#endif // TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP
diff --git a/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp
new file mode 100644
index 0000000..15b35c1
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp
@@ -0,0 +1,34 @@
+#ifndef TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
+#define TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::interrupt_handling
+{
+ /**
+ * @brief Represents the CPU state during an interrupt.
+ *
+ * Some interrupts push an error code, while others do not. The full list
+ * of which vector number contains the error code can be found here: https://wiki.osdev.org/Exceptions
+ */
+ struct [[gnu::packed]] interrupt_frame
+ {
+ // uint64_t error_code; ///< Error code only pushed by some exceptions, therefore it is commented out.
+ uint64_t ip; ///< Instruction pointer at the time of the interrupt.
+ uint64_t cs; ///< Code segment selector indicating privilege level.
+ uint64_t flags; ///< CPU flags (RFLAGS) storing processor state.
+ uint64_t sp; ///< Stack pointer at the time of the interrupt.
+ uint64_t ss; ///< Stack segment selector, usually unused in 64-bit mode.
+ };
+
+ /**
+ * @brief Generic interrupt handler function.
+ *
+ * @param frame Pointer to the interrupt frame containing CPU state.
+ */
+ [[gnu::interrupt]]
+ auto generic_interrupt_handler(interrupt_frame * frame) -> void;
+
+} // namespace teachos::arch::interrupt_handling
+
+#endif // TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp
new file mode 100644
index 0000000..3c43304
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp
@@ -0,0 +1,30 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
+
+#include <cstdint>
+
+namespace teachos::arch::kernel::cpu
+{
+ /**
+ * @brief Far Pointer. Address to function located in another code segment.
+ */
+ struct far_pointer
+ {
+ void (*function)(); ///< Address of the function we want to call. (0-63)
+ context_switching::interrupt_descriptor_table::segment_selector
+ selector; ///< Segment selector pointing to the GDT entry we want to load into register CS. (64-79)
+ };
+
+ /**
+ * @brief Far call - A call to an instruction located in a different segment than the current code segment but at the
+ * same privilege level.
+ *
+ * @param pointer 64-bit operand size far pointer that we want to call.
+ */
+ auto call(far_pointer pointer) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp
new file mode 100644
index 0000000..68b950d
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp
@@ -0,0 +1,27 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP
+
+#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp"
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::kernel::cpu
+{
+
+ /**
+ * @brief Returns the value in the GDTR register.
+ *
+ * @return Value of GDTR register.
+ */
+ auto store_global_descriptor_table() -> context_switching::segment_descriptor_table::global_descriptor_table_pointer;
+
+ /**
+ * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR).
+ */
+ auto load_global_descriptor_table(
+ context_switching::segment_descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp
new file mode 100644
index 0000000..cb800d0
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp
@@ -0,0 +1,27 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::kernel::cpu
+{
+ /**
+ * @brief Returns the value in the IDTR register.
+ *
+ * @return Value of IDTR register.
+ */
+ auto store_interrupt_descriptor_table()
+ -> context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer;
+
+ /**
+ * @brief Loads the interrupt_descriptor_table_pointer into the interrupt descriptor table register (IDTR).
+ */
+ auto load_interrupt_descriptor_table(
+ context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp
new file mode 100644
index 0000000..48707dc
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp
@@ -0,0 +1,21 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
+
+namespace teachos::arch::kernel::cpu
+{
+ /**
+ * @brief Sets the interrupt flag (IF) in the EFLAGS register.
+ * This allows the processor to respond to maskable hardware interrupts.
+ */
+ auto set_interrupt_flag() -> void;
+
+ /**
+ * @brief Clears the interrupt flag (IF) in the EFLAGS register.
+ * This will stop the processor to respond to maskable hardware interrupts and needs to be done before changing the
+ * Interrupt Descriptor Table with lidt.
+ */
+ auto clear_interrupt_flag() -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp
new file mode 100644
index 0000000..99d6378
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp
@@ -0,0 +1,64 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::kernel::cpu
+{
+ /**
+ * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER).
+ *
+ * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions
+ * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for
+ * more information.
+ */
+ enum class efer_flags : uint64_t
+ {
+ SCE = 1UL << 0UL, ///< System Call Extensions.
+ LME = 1UL << 8UL, ///< Long Mode Enabled.
+ LMA = 1UL << 10UL, ///< Long Mode Active.
+ NXE = 1UL << 11UL, ///< No-Execute Enable.
+ SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable.
+ LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable.
+ FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR.
+ TCE = 1UL << 15UL, ///< Translation Cache Extension.
+ };
+
+ /**
+ * @brief Reads a 64-bit from the Model-Specific Register (MSR).
+ *
+ * @note This function reads the value of an MSR specified by the given address. It combines the lower and upper
+ * 32-bits of the MSR value read using the 'rdmsr' instruction and returns it as a 64-bit unsigned integer.
+ *
+ * @param msr The address of the MSR to read.
+ * @return The 64-bit value read from the MSR.
+ */
+ auto read_msr(uint32_t msr) -> uint64_t;
+
+ /**
+ * @brief Writes a 64-bit value to a Model-Specific Register (MSR).
+ *
+ * @note This function writes a 64-bit value to the MSR specified by the given address.
+ * It splits the 64-bit value into two 32-bit parts and writes them using the
+ * `wrmsr` instruction.
+ *
+ * @param msr The address of the MSR to write to.
+ * @param new_value The 64-bit value to write to the MSR.
+ */
+ auto write_msr(uint32_t msr, uint64_t new_value) -> void;
+
+ /**
+ * @brief Sets a specific bit in the Extended Feature Enable Register (EFER), which is a Model-Specific Register
+ * (MSR).
+ *
+ * @note This function reads the current value of the EFER register, ORs the specified
+ * bit with the current value, and writes the updated value back to the EFER register.
+ *
+ * @param flag The flag to set in the EFER register.
+ */
+ auto set_efer_bit(efer_flags flag) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp
new file mode 100644
index 0000000..a236452
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp
@@ -0,0 +1,97 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
+
+namespace teachos::arch::kernel::cpu
+{
+ /**
+ * @brief Clear all Data Segment registers (DS / ES / FS / GS).
+ */
+ auto reload_data_segment_registers() -> void;
+
+ /**
+ * @brief Updates the value of the Data Segment Register (DS), Extra Segment Register (ES), Thread-Local Storage
+ * Registers (FS / GS).
+ *
+ * @note The Stack Segment Register (SS) value should also be updated, but the value can not be directly set in
+ * comparsion to the other registers. This is the case because the register is used for stack management and can not
+ * be directly changed, instead this has to be done by a special instruction. Therefore
+ * validate_data_segment_registers should only be called after set_code_segment_register has been called as well.
+ *
+ * @param data_segment Value that should be loaded into the registers.
+ */
+ auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) -> void;
+
+ /**
+ * @brief Returns the Segment Selector pointing to the Code Segment that has been loaded into the Code Segment
+ * Register (CS).
+ *
+ * @note The CS register can not be directly changed, instead a Far Return has to be executed to change it
+ *
+ * @return Segment Selector pointing to the currently loaded Code Segment.
+ */
+ [[gnu::section(".user_text")]]
+ auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector;
+
+ /**
+ * @brief Validates that all Data Segment Registers (DS / ES / FS / GS / SS) are the same as the given Data Segment
+ * and asserts and stops the application if they are not.
+ *
+ * @note This is only the case after set_code_segment_register has been executed as well, because it makes a far
+ * return that updates the SS register.
+ *
+ * @param data_segment Value that should be loaded into all Data Segment Registers.
+ */
+ auto validate_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment)
+ -> void;
+
+ /**
+ * @brief Validates that the Code Segment Register (CS) is the same as the given Code Segment
+ * and asserts and stops the application if they are not.
+ *
+ * @param code_segment Value that should be loaded into the Code Segment Register.
+ */
+ auto validate_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector code_segment)
+ -> void;
+
+ /**
+ * @brief Simply forwards the call to validate_data_segment_registers and validate_code_segment_register and ensures
+ * that all Segment Registers, have been configured correctly.
+ *
+ * @note If all Segment Register have been set correctly the Context Switch using the set_code_segment_register method
+ * was successfull and the Privilege Level has been changed.
+ *
+ * @param data_segment Value that should be loaded into all Data Segment Registers.
+ * @param code_segment Value that should be loaded into the Code Segment Register.
+ */
+ auto validate_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment,
+ context_switching::interrupt_descriptor_table::segment_selector code_segment) -> void;
+
+ /**
+ * @brief Sets the value of the Code Segment Register (CS), this is achieved using a Far Return.
+ *
+ * @note The Far Return used by this method, will cause the context to switch, because we are changing from the
+ * current Code Segment and it's associated Privilege Level to another Code Segment. The given method will then be
+ * called in the new context and it should be possible to call validate_segment_registers, with the same values
+ * without assertions if the switch was successful.
+ *
+ * To achieve this Far Return we call IRETQ, which expects the stack to be defined a certain way to achieve that we:
+ * 1. Push the Data Segment Selector
+ * 2. Push the current Stack Pointer
+ * 3. Push Eflags
+ * 4. Push Code Segment Selector
+ * 5. Push Return Address
+ *
+ * @param data_segment Data Segment that should be loaded into the SS register.
+ * @param code_segment Code Segment that should be loaded into the CS register.
+ * @param address Function that we want to call in the new context created by the given Code Segment.
+ */
+ [[gnu::naked]]
+ auto set_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector data_segment,
+ context_switching::interrupt_descriptor_table::segment_selector code_segment,
+ uint64_t address) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp
new file mode 100644
index 0000000..7c856f1
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp
@@ -0,0 +1,24 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::kernel::cpu
+{
+
+ /**
+ * @brief Returns the value in the LTR register.
+ *
+ * @return Value of LTR register.
+ */
+ auto store_task_register() -> uint16_t;
+
+ /**
+ * @brief Loads the gdt offset to the tss segment descriptor into the task register (TR).
+ */
+ auto load_task_register(uint16_t gdt_offset) -> void;
+
+} // namespace teachos::arch::kernel::cpu
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/halt.hpp b/arch/x86_64/pre/include/arch/kernel/halt.hpp
new file mode 100644
index 0000000..377acc0
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/halt.hpp
@@ -0,0 +1,13 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
+
+namespace teachos::arch::kernel
+{
+ /**
+ * @brief Halts the kernel execution, meaning any code after a call to this will not run anymore.
+ */
+ extern "C" [[noreturn]] auto halt() -> void;
+
+} // namespace teachos::arch::kernel
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/main.hpp b/arch/x86_64/pre/include/arch/kernel/main.hpp
new file mode 100644
index 0000000..a13e5f4
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/kernel/main.hpp
@@ -0,0 +1,13 @@
+#ifndef TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
+
+namespace teachos::arch::kernel
+{
+ /**
+ * @brief Initalizes the kernel system.
+ */
+ auto main() -> void;
+
+} // namespace teachos::arch::kernel
+
+#endif // TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp
new file mode 100644
index 0000000..a86c9b7
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp
@@ -0,0 +1,67 @@
+#ifndef TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP
+#define TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP
+
+// #include "arch/memory/allocator/physical_frame.hpp"
+// #include "arch/memory/multiboot/reader.hpp"
+
+#include <optional>
+
+namespace x86_64::memory
+{
+ /**
+ * @brief Allocates memory linearly using memory areas read from the multiboot2 information pointer and leaks any
+ * deallocated frames.
+ */
+ struct area_frame_allocator
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param mem_info Structure containg all relevant information to map and allocate memory.
+ */
+ area_frame_allocator(multiboot::memory_information const & mem_info);
+
+ /**
+ * @brief Allocate memory by finding and returning a free physical frame.
+ *
+ * @note The physical_frame allocation executes multiple checks before returning
+ * the physical_frame that is available to allocate. It must at least
+ * do the following:
+ * - check if the next_free_frame is within the current_area
+ * - check if the next_free_frame is actually free
+ * - update the next_free_frame after finding a free physical_frame
+ *
+ * @return next free physical frame or nullopt if none was found.
+ */
+ auto allocate_frame() -> std::optional<physical_frame>;
+
+ /**
+ * @brief Deallocates a previously allocated physical frame.
+ *
+ * @note Simply does nothing, because the simply area frame
+ * allocator implementation does not keep track of free or used frames and can therefore not deallocate, because it
+ * does not know which frames have been alocated in the first place.
+ *
+ * @param physical_frame Previously allocated physical_frame that should be deallocated.
+ */
+ auto deallocate_frame(physical_frame const & physical_frame) -> void;
+
+ private:
+ /**
+ * @brief Find the next memory area and write it into current_area.
+ */
+ auto choose_next_area() -> void;
+
+ physical_frame next_free_frame; ///< The physical_frame after the last allocated one.
+ std::optional<multiboot::memory_area> current_area; ///< The current memory area.
+ multiboot::memory_area_container const
+ memory_areas; ///< All memory areas in custom container allows to use std::ranges.
+ physical_frame const kernel_start; ///< The start address of the kernel code in memory.
+ physical_frame const kernel_end; ///< The end address of the kernel code in memory.
+ physical_frame const multiboot_start; ///< The start address of the multiboot code in memory.
+ physical_frame const multiboot_end; ///< The end address of the multiboot code in memory.
+ };
+
+} // namespace x86_64::memory
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp b/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp
new file mode 100644
index 0000000..2d3f4ae
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp
@@ -0,0 +1,21 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
+
+#include "arch/memory/allocator/physical_frame.hpp"
+
+#include <optional>
+
+namespace teachos::arch::memory::allocator
+{
+ /**
+ * @brief Frame allocator concept required for allocating and deallocating physical frames in memory.
+ */
+ template<typename T>
+ concept FrameAllocator = requires(T t, physical_frame const & a) {
+ { t.allocate_frame() } -> std::same_as<std::optional<physical_frame>>;
+ { t.deallocate_frame(a) } -> std::same_as<void>;
+ };
+
+} // namespace teachos::arch::memory::allocator
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp
new file mode 100644
index 0000000..1ceb74d
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp
@@ -0,0 +1,74 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
+
+#include "arch/memory/allocator/concept.hpp"
+#include "arch/memory/allocator/physical_frame.hpp"
+
+#include <array>
+
+namespace teachos::arch::memory::allocator
+{
+ namespace
+ {
+ uint8_t constexpr TINY_ALLOCATOR_FRAMES_COUNT = 3U;
+ }
+
+ /**
+ * @brief Allocates memory using memory areas read from the multiboot2 information pointer. Does not allocate its own
+ * frames, but uses the necessary three frames provided by another allocator to map one virtual level 1 page entry and
+ * the necessary upper layers.
+ */
+ struct tiny_frame_allocator
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @tparam T Contract the allocator that should be used to actually allocate and deallocate, the underlying three
+ * frames has to follow.
+ *
+ * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
+ * entries when the underlying frames are created.
+ */
+ template<allocator::FrameAllocator T>
+ tiny_frame_allocator(T & allocator)
+ : frames{}
+ {
+ // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(),
+ // does not work because it would set the value correctly but because we pass it as an std::optional it would not
+ // set the engaged flag. Meaning the has_value() method would still return false.
+ for (auto & frame : frames)
+ {
+ auto allocated = allocator.allocate_frame();
+ if (allocated.has_value())
+ {
+ frame.emplace(allocated.value());
+ }
+ }
+ }
+
+ /**
+ * @brief Allocate memory by finding and returning one of the three free physical frames.
+ *
+ * @return First free physical frames of the three frames held by this allocator or nullopt if we used up all three
+ * frames already.
+ */
+ auto allocate_frame() -> std::optional<physical_frame>;
+
+ /**
+ * @brief Deallocates one of the three previously allocated physical frames.
+ *
+ * @note If more than the three frames are deallocated the method will halt execution, because it can only hold 3
+ * frames.
+ *
+ * @param physical_frame Previously allocated physical_frame that should be deallocated.
+ */
+ auto deallocate_frame(physical_frame const & physical_frame) -> void;
+
+ private:
+ std::array<std::optional<physical_frame>, TINY_ALLOCATOR_FRAMES_COUNT> frames =
+ {}; ///< Container that holds the frames allocated by another allocator.
+ };
+
+} // namespace teachos::arch::memory::allocator
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/pre/include/arch/memory/heap/bump_allocator.hpp
new file mode 100644
index 0000000..011f45c
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/bump_allocator.hpp
@@ -0,0 +1,48 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP
+
+#include "arch/memory/heap/heap_allocator.hpp"
+
+#include <atomic>
+#include <cstdint>
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Simple heap allocator, which allocates linearly and leaks all allocated memory, because it does not really
+ * deallocate anything.
+ */
+ struct bump_allocator : heap_allocator
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param heap_start Start of the allocatable heap area
+ * @param heap_end End of the allocatable heap area (Start + Size)
+ */
+ bump_allocator(std::size_t heap_start, std::size_t heap_end)
+ : heap_start{heap_start}
+ , heap_end{heap_end}
+ , next{heap_start}
+ {
+ // Nothing to do
+ }
+
+ auto allocate(std::size_t size) -> void * override;
+
+ /**
+ * @copybrief heap_allocator::deallocate
+ *
+ * @note Simply does nothing, because this allocator leaks all memory
+ */
+ auto deallocate(void * pointer) noexcept -> void override;
+
+ private:
+ std::size_t heap_start; ///< Start of the allocatable heap area
+ std::size_t heap_end; ///< End of the allocatable heap area
+ std::atomic_uint64_t next; ///< Current address, which is the start of still unused allocatable heap area
+ };
+
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/pre/include/arch/memory/heap/global_heap_allocator.hpp
new file mode 100644
index 0000000..c98c130
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/global_heap_allocator.hpp
@@ -0,0 +1,118 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
+
+#include "arch/memory/heap/heap_allocator.hpp"
+#include "arch/memory/heap/user_heap_allocator.hpp"
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Possible types that should be constructed by the register_heap_allocator factory method.
+ * Creates the underlying heap allocator instance that is then used by all global allocations using new and delete
+ */
+ enum class heap_allocator_type : uint8_t
+ {
+ NONE, ///< Don't use any heap allocation implementation, this will result in all calls of new and delte halting
+ ///< further execution of the kernel
+ BUMP, ///< Use the bump allocator as the heap allocation implementation, be aware that using this allocator leaks
+ ///< memory, because there is no delete implementation
+ LINKED_LIST ///< Use the linked list allocator as the heap implementation, recommended because it does not leak
+ ///< memory
+ };
+
+ /**
+ * @brief Global instance of a heap allocator implementation created by the factory method pattern @see
+ * https://refactoring.guru/design-patterns/factory-method for more information.
+ *
+ * @note Can only be registered once and only once the kernel and the heap part of the kernel has been remapped
+ * successfully. If the instance is created before than the device will abort, because it acceses unmapped memory
+ * areas.
+ */
+ struct global_heap_allocator
+ {
+ /**
+ * @brief Registers the heap allocation implementation that should be used by the global heap allocator.
+ * Meaning all future calls to the global new or delete will be forwarded to the allocate and deallocate calls of
+ * the underlying heap allocation implementation
+ *
+ * @param new_type Type of the heap allocation implementation we want to instantiate
+ */
+ static auto register_heap_allocator(heap_allocator_type new_type) -> void;
+
+ /**
+ * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area.
+ * Simply forwards the call to the allocate method of the registered heap_allocation implementation
+ *
+ * @param size Amount of bytes that should be allocated
+ * @return void* Pointer to the start of the allocatable memory area
+ */
+ static auto kmalloc(std::size_t size) -> void *;
+
+ /**
+ * @brief Deallocated all memory associated with the memory area starting from the given pointer address.
+ * Simply forwards the call to the deallocate method of the registered heap_allocation implementation
+ *
+ * @param pointer Previously allocated memory area, that should now be freed
+ */
+ static auto kfree(void * pointer) noexcept -> void;
+
+ /**
+ * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area.
+ * Simply forwards the call to the allocate method of the registered heap_allocation implementation
+ *
+ * @param size Amount of bytes that should be allocated
+ * @return void* Pointer to the start of the allocatable memory area
+ */
+ [[gnu::section(".user_text")]]
+ static auto malloc(std::size_t size) -> void *;
+
+ /**
+ * @brief Deallocated all memory associated with the memory area starting from the given pointer address.
+ * Simply forwards the call to the deallocate method of the registered heap_allocation implementation
+ *
+ * @param pointer Previously allocated memory area, that should now be freed
+ */
+ [[gnu::section(".user_text")]]
+ static auto free(void * pointer) noexcept -> void;
+
+ private:
+ static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory
+ [[gnu::section(".user_data")]] static user_heap_allocator *
+ user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory
+
+ /**
+ * @brief Either returns the previously registered heap allocated or halts further execution
+ *
+ * @return Reference to the registered kernel heap allocation
+ */
+ static auto kernel() -> heap_allocator &;
+
+ /**
+ * @brief Either returns the previously registered heap allocated or halts further execution
+ *
+ * @return Reference to the registered user heap allocation
+ */
+ [[gnu::section(".user_text")]]
+ static auto user() -> user_heap_allocator &;
+ };
+} // namespace teachos::arch::memory::heap
+
+[[gnu::section(".user_text")]]
+auto operator new(std::size_t size) -> void *;
+
+[[gnu::section(".user_text")]]
+auto operator delete(void * pointer) noexcept -> void;
+
+[[gnu::section(".user_text")]]
+auto operator delete(void * pointer, std::size_t size) noexcept -> void;
+
+[[gnu::section(".user_text")]]
+auto operator new[](std::size_t size) -> void *;
+
+[[gnu::section(".user_text")]]
+auto operator delete[](void * pointer) noexcept -> void;
+
+[[gnu::section(".user_text")]]
+auto operator delete[](void * pointer, std::size_t size) noexcept -> void;
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/heap_allocator.hpp b/arch/x86_64/pre/include/arch/memory/heap/heap_allocator.hpp
new file mode 100644
index 0000000..420a1d3
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/heap_allocator.hpp
@@ -0,0 +1,45 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::memory::heap
+{
+ std::size_t constexpr KERNEL_HEAP_START = 0x100000000;
+ std::size_t constexpr KERNEL_HEAP_SIZE = 100 * 1024;
+ std::size_t constexpr USER_HEAP_START = 0x100019000; // Starts directly after kernel heap
+ std::size_t constexpr USER_HEAP_SIZE = 100 * 1024;
+
+ /**
+ * @brief Heap allocator interface containing methods required to allocate and deallocate heap memory areas
+ */
+ struct heap_allocator
+ {
+ /**
+ * @brief Virtual default destructor, created to ensure that if a pointer to this class is used and deleted, we will
+ * also call the derived base class destructor. Deleting a base class destructor that does not have a virtual
+ * destructor is undefined behaviour, because the derived class destructor originally instantiated with new is never
+ * called. This can cause potential memory leaks, because derived classes can not clean up their internal members as
+ * expected and instead simply leak them
+ */
+ virtual ~heap_allocator() {}
+
+ /**
+ * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area
+ *
+ * @param size Amount of bytes that should be allocated
+ * @return void* Pointer to the start of the allocatable memory area
+ */
+ virtual auto allocate(std::size_t size) -> void * = 0;
+
+ /**
+ * @brief Deallocates all memory associated with the given pointer address.
+ * Simply deallocates the amount of memory created with the corresponding call to allocate
+ *
+ * @param pointer Previously allocated memory area, that should now be freed
+ */
+ virtual auto deallocate(void * pointer) noexcept -> void = 0;
+ };
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/pre/include/arch/memory/heap/linked_list_allocator.hpp
new file mode 100644
index 0000000..bbbad19
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/linked_list_allocator.hpp
@@ -0,0 +1,120 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
+
+#include "arch/memory/heap/heap_allocator.hpp"
+#include "arch/memory/heap/memory_block.hpp"
+
+#include <kstd/mutex.hpp>
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information,
+ * containing the size and pointer to the next hole. Resulting in a singly linked list.
+ */
+ struct linked_list_allocator : heap_allocator
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param heap_start Start of the allocatable heap area
+ * @param heap_end End of the allocatable heap area (Start + Size)
+ */
+ linked_list_allocator(std::size_t heap_start, std::size_t heap_end);
+
+ /**
+ * @copybrief heap_allocator::allocate
+ *
+ * @note The specified size is used to find a free memory block with the exact same size, meaning we can remove that
+ * free memory block from the free list and simply return its address. Or it has to be big enough to hold the size
+ * and alteast enough memory for another free memory block entry (16 bytes). If the amount of memory of that free
+ * memory block is in between we cannot use it for our allocation, because we could only return it to the user, but
+ * the additional bytes, could not be used to create a free memory block. Additionaly the user couldn't know
+ * they received more memory than wanted. Therefore the memory would simply be unused and because it is neither
+ * allocated nor deallocated would never be indexed by the free memory list. We would therefore permanently loose
+ * that memory, to prevent that allocation into free memory blocks like that are impossible.
+ */
+ auto allocate(std::size_t size) -> void * override;
+
+ auto deallocate(void * pointer) noexcept -> void override;
+
+ private:
+ /**
+ * @brief Returns the smallest allocatable block of heap memory.
+ *
+ * @return Smallest allocatable block of heap memory.
+ */
+ auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); }
+
+ /**
+ * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to remove from the free list and return for the allocation.
+ *
+ * @return Previous start address of the memory block we removed, because it can now be used for the allocation.
+ */
+ auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block) -> void *;
+
+ /**
+ * @brief Splits the given free memory block into two, where the latter block keeps being free and the first
+ * part will be used for the allocation.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to split into a size part for the allocation and the rest for
+ * future allocations.
+ * @param size Size we want to allocate at the start of the free memory block.
+ *
+ * @return Previous start address of the memory block we just split, because it can now be used for the allocation.
+ */
+ auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size)
+ -> void *;
+
+ /**
+ * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to remove from the free list and return for the allocation.
+ * @param new_block Replaces the current block with the given new block can be nullptr, meaning the free list will
+ * end here.
+ *
+ * @return Previous start address of the memory block we removed, because it can now be used for the allocation.
+ */
+ auto replace_free_memory_block(memory_block * previous_block, memory_block * current_block,
+ memory_block * new_block) -> void *;
+
+ /**
+ * @brief Combines multiple free memory blocks into one if they are adjacent.
+ *
+ * @note The internal algorithm for recombination functions like this:
+ * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and
+ * we can therefore set the first entry to our newly created entry. This entry is created in the now deallocated
+ * memory area.
+ * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a
+ * new free memory block of the given size and set the previous next to our block and the next of our block to
+ * the current block.
+ * 3. If the current block is adjacent the start address of the newly created block stays the same, but the size
+ * increases by the amount in the current memory block header. After reading it we also clear the header.
+ * 4. If the previous block is adjacent the size of the previous block simply increases to include the given
+ * size as well.
+ * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of
+ * the region we are trying to deallocate has been freed before. Which would result in a double free therefore
+ * we halt the execution of the program.
+ *
+ * @param previous_block Free memory block before the block to deallocate in our heap memory.
+ * @param current_block Free memory block after the block to deallocate in our heap memory.
+ * @param pointer Block to deallocate.
+ * @param size Size of the block we want to deallocate.
+ */
+ auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer,
+ std::size_t size) -> void;
+
+ memory_block * first; ///< First free entry in our memory.
+ kstd::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once.
+ };
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/pre/include/arch/memory/heap/memory_block.hpp
new file mode 100644
index 0000000..9d1fb02
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/memory_block.hpp
@@ -0,0 +1,39 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Block containing free memory, pointing to the next free hole (nullptr) if there is none.
+ * Forms a singly linked list of free memory blocks that we can callocate memory into.
+ */
+ struct memory_block
+ {
+ /**
+ * @brief Constructor. Clears all memory from the place it was allocated until the end (address +
+ * size).
+ *
+ * @param size Amount of free memory of this specific hole.
+ * @param next Optional pointer to the next free memory.
+ */
+ [[gnu::section(".user_text")]]
+ memory_block(std::size_t size, memory_block * next);
+
+ /**
+ * @brief Destructor. Clears all internal memory.
+ *
+ * @note Used so the memory can be reused to construct other classes into, without having the old values.
+ * Required because we cannot call delete, because it causes "undefined reference to `sbrk`".
+ */
+ [[gnu::section(".user_text")]]
+ ~memory_block();
+
+ std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the
+ ///< size variable and the pointer to the next hole.
+ memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none.
+ };
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/heap/user_heap_allocator.hpp b/arch/x86_64/pre/include/arch/memory/heap/user_heap_allocator.hpp
new file mode 100644
index 0000000..3b47f15
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/heap/user_heap_allocator.hpp
@@ -0,0 +1,149 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP
+
+#include "arch/memory/heap/memory_block.hpp"
+
+// #include <kstd/mutex.hpp>
+#include <kstd/mutex.hpp>
+#include <optional>
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information,
+ * containing the size and pointer to the next hole. Resulting in a singly linked list.
+ */
+ struct user_heap_allocator
+ {
+ /**
+ * @brief Constructor.
+ */
+ user_heap_allocator() = default;
+
+ /**
+ * @copybrief heap_allocator::allocate
+ *
+ * @note The specified size is used to find a free memory block with the exact same size, meaning we can remove that
+ * free memory block from the free list and simply return its address. Or it has to be big enough to hold the size
+ * and alteast enough memory for another free memory block entry (16 bytes). If the amount of memory of that free
+ * memory block is in between we cannot use it for our allocation, because we could only return it to the user, but
+ * the additional bytes, could not be used to create a free memory block. Additionaly the user couldn't know
+ * they received more memory than wanted. Therefore the memory would simply be unused and because it is neither
+ * allocated nor deallocated would never be indexed by the free memory list. We would therefore permanently loose
+ * that memory, to prevent that allocation into free memory blocks like that are impossible.
+ */
+ [[gnu::section(".user_text")]]
+ auto allocate(std::size_t size) -> void *;
+
+ /**
+ * @copybrief heap_allocator::deallocate
+ */
+ [[gnu::section(".user_text")]]
+ auto deallocate(void * pointer) noexcept -> void;
+
+ private:
+ /**
+ * @brief Returns the smallest allocatable block of heap memory.
+ *
+ * @return Smallest allocatable block of heap memory.
+ */
+ [[gnu::section(".user_text")]] auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); }
+
+ /**
+ * @brief Checks if the given memory block is big enough and if it is allocates into the current block.
+ *
+ * @note Adjusts the link of the previous memory block to the new smaller remaining block. If the allocation used
+ * the complete block instead the previous block will point to the next block of the current memroy block that was
+ * used for the allocation.
+ *
+ * @return Allocated usable memory area.
+ */
+ [[gnu::section(".user_text")]] auto
+ allocate_into_memory_block_if_big_enough(memory_block * current, memory_block * previous, std::size_t total_size)
+ -> std::optional<void *>;
+
+ /**
+ * @brief Special functionality fo the user heap allocator. Which will result in it being expanded by a syscall with
+ * addtionally 100 KiB, which are mapped into the page table. Will always work until there is no physical memory
+ * left.
+ *
+ * @return Start of the newly with syscall allocated free memory block. Nullptr if the syscall failed.
+ */
+ [[gnu::section(".user_text")]] auto expand_heap_if_full() -> memory_block *;
+
+ /**
+ * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to remove from the free list and return for the allocation.
+ *
+ * @return Previous start address of the memory block we removed, because it can now be used for the allocation.
+ */
+ [[gnu::section(".user_text")]]
+ auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block) -> void *;
+
+ /**
+ * @brief Splits the given free memory block into two, where the latter block keeps being free and the first
+ * part will be used for the allocation.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to split into a size part for the allocation and the rest for
+ * future allocations.
+ * @param size Size we want to allocate at the start of the free memory block.
+ *
+ * @return Previous start address of the memory block we just split, because it can now be used for the allocation.
+ */
+ [[gnu::section(".user_text")]]
+ auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size)
+ -> void *;
+
+ /**
+ * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it.
+ *
+ * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to
+ * allocate the required size into.
+ * @param current_block Free memory block we want to remove from the free list and return for the allocation.
+ * @param new_block Replaces the current block with the given new block can be nullptr, meaning the free list will
+ * end here.
+ *
+ * @return Previous start address of the memory block we removed, because it can now be used for the allocation.
+ */
+ [[gnu::section(".user_text")]]
+ auto replace_free_memory_block(memory_block * previous_block, memory_block * current_block,
+ memory_block * new_block) -> void *;
+
+ /**
+ * @brief Combines multiple free memory blocks into one if they are adjacent.
+ *
+ * @note The internal algorithm for recombination functions like this:
+ * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and
+ * we can therefore set the first entry to our newly created entry. This entry is created in the now deallocated
+ * memory area.
+ * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a
+ * new free memory block of the given size and set the previous next to our block and the next of our block to
+ * the current block.
+ * 3. If the current block is adjacent the start address of the newly created block stays the same, but the size
+ * increases by the amount in the current memory block header. After reading it we also clear the header.
+ * 4. If the previous block is adjacent the size of the previous block simply increases to include the given
+ * size as well.
+ * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of
+ * the region we are trying to deallocate has been freed before. Which would result in a double free therefore
+ * we halt the execution of the program.
+ *
+ * @param previous_block Free memory block before the block to deallocate in our heap memory.
+ * @param current_block Free memory block after the block to deallocate in our heap memory.
+ * @param pointer Block to deallocate.
+ * @param size Size of the block we want to deallocate.
+ */
+ [[gnu::section(".user_text")]]
+ auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer,
+ std::size_t size) -> void;
+
+ memory_block * first = {}; ///< First free entry in our memory.
+ kstd::mutex mutex = {}; ///< Mutex to ensure only one thread calls allocate or deallocate at once.
+ };
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/main.hpp b/arch/x86_64/pre/include/arch/memory/main.hpp
new file mode 100644
index 0000000..d51815f
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/main.hpp
@@ -0,0 +1,30 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
+
+#include "arch/memory/paging/page_entry.hpp"
+
+#include <cstdint>
+
+namespace teachos::arch::memory
+{
+
+ /**
+ * @brief Maps a heap section to a page.
+ *
+ * @param heap_start Start-address of the heap.
+ * @param heap_size Size of the heap.
+ * @param additional_flags Additional flags to apply to the page entry.
+ */
+ auto remap_heap(std::size_t heap_start, std::size_t heap_size, paging::entry::bitset additional_flags) -> void;
+
+ /**
+ * @brief Initializes memory management.
+ *
+ * @note Enables the necessary register flags and remaps the kernel,
+ * elf_sections, vga_text and the heap.
+ */
+ auto initialize_memory_management() -> void;
+
+} // namespace teachos::arch::memory
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp
new file mode 100644
index 0000000..348c159
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp
@@ -0,0 +1,170 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
+
+// #include "arch/memory/multiboot/info.hpp"
+// #include "arch/stl/container.hpp"
+// #include "arch/stl/contiguous_pointer_iterator.hpp"
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::memory::multiboot
+{
+ /**
+ * @brief Defines all elf section types an elf section header can have.
+ *
+ * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information.
+ */
+ enum struct elf_section_type : uint32_t
+ {
+ INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out.
+ PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE).
+ SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table.
+ STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and debugging null-terminated strings.
+ RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems.
+ SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols.
+ DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information.
+ NOTE, ///< (SHT_NOTE) Stores information that marks files in some way.
+ EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss).
+ RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems.
+ UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics.
+ DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking.
+ INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void.
+ TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void.
+ PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other
+ ///< initalization functions () -> void.
+ };
+
+ /**
+ * @brief Defines helper function for all states that the elf section flags of an elf section header can
+ * have.
+ *
+ * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information.
+ */
+ struct elf_section_flags
+ {
+ /**
+ * @brief Possible set bits in our underlying std::bitset and the meaning when they are set.
+ */
+ enum bitset : uint32_t
+ {
+ WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section
+ ///< is assumed to be READONLY and only that flag is shown in the objdump.
+ OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution.
+ ///< ALLOC flag is shown in the objdump.
+ EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump.
+ DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section.
+ CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings.
+ SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX =
+ 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info)
+ ///< additional_information variable.
+ PRESERVE_ORDERING_AFTER_COMBINATION =
+ 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section.
+ REQUIRES_SPECIAL_OS_PROCESSING =
+ 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or
+ ///< data, which does not confirm to standard ELF specifications.
+ SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group.
+ HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data.
+ COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data.
+ SPECIAL_ORDERING_REQUIREMENTS =
+ 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it
+ ///< should be ordered in relation to other sections of the same type.
+ EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or
+ ///< allocated, used for LTO (Link-Time Optimizations).
+ };
+
+ /**
+ * @brief Constructor.
+ *
+ * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to
+ * allow reading the state of single bits more easily.
+ */
+ explicit elf_section_flags(uint64_t flags)
+ : flags(flags)
+ {
+ // Nothing to do
+ }
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * std::bitset. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying std::bitset.
+ */
+ auto contains_flags(std::bitset<64U> other) const -> bool;
+
+ /**
+ * @brief Allows to compare the underlying std::bitset of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying std::bitset of both types is the same.
+ */
+ auto operator==(elf_section_flags const & other) const -> bool = default;
+
+ private:
+ std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating
+ ///< system specific semantics and bits 29 - 32 are reserved for processor specific
+ ///< semantics. Bits 33 - 64 are unused for compatability with ELF32.
+ };
+
+ /**
+ * @brief Defines the data included in a section header, where each section has exactly one section header.
+ *
+ * @note See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information.
+ */
+ struct elf_section_header
+ {
+ uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section.
+ elf_section_type type; ///< Categorizes the sections content and semantics.
+ elf_section_flags flags; ///< 1-bit flgas that describe section attributes.
+ uint64_t physical_address; ///< If section appears in memory image of a process, gives address at which the
+ ///< sections first byte should reside, otherwise 0.
+ uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS
+ ///< contains the conceptual placement instead (because it occupies no space in the file).
+ uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always
+ ///< occupy no space in the file.
+ uint32_t other_section; ///< Section header table index link, behaviour varies on type
+ ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link.
+ uint32_t additional_information; ///< Extra information, behaviour varies on type
+ ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link.
+ uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value
+ ///< of address_alignment. Value 0 or 1 mean no alignment constraints.
+ uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in
+ ///< bytes of each entry.
+
+ /**
+ * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the
+ * sections table.
+ *
+ * @return Whether the current section header is actually null or not, requires all fields besides section_size and
+ * other_section to contain 0.
+ */
+ auto is_null() const -> bool;
+ };
+
+ // /**
+ // * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
+ // * multi_boot_tag_type::ELF_SECTIONS.
+ // *
+ // * @note The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC
+ // section
+ // * and only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE.
+ // */
+ // struct elf_symbols_section_header
+ // {
+ // tag info; ///< Basic multi_boot_tag information.
+ // uint32_t number_of_sections; ///< Number of sections in the sections array.
+ // uint32_t entry_size; ///< Size of each entry in the sections array.
+ // uint32_t section_index; ///< Index to the string table used for symbol names.
+ // std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data.
+ // ///< contained in the section, to ensure byte alignment is actually 4 byte.
+ // };
+
+ // using elf_section_header_container = stl::container<stl::contiguous_pointer_iterator<elf_section_header>>;
+
+} // namespace teachos::arch::memory::multiboot
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp
new file mode 100644
index 0000000..c5464cb
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp
@@ -0,0 +1,58 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
+
+// #include "arch/memory/multiboot/elf_symbols_section.hpp"
+// #include "arch/memory/multiboot/memory_map.hpp"
+
+#include "arch/memory/multiboot/elf_symbols_section.hpp"
+
+#include <cstdint>
+#include <multiboot2/information.hpp>
+#include <span>
+
+namespace teachos::arch::memory::multiboot
+{
+ /**
+ * @brief Contains all relevant information to map and allocate memory that is read from the multiboot2 information
+ * structure.
+ */
+ struct memory_information
+ {
+ std::size_t kernel_start; ///< Start address of the kernel code in memory.
+ std::size_t kernel_end; ///< End address of the kernel code in memory.
+ multiboot2::elf_symbols; ///< Contains non-owning pointers to all kernel sections.
+ std::size_t multiboot_start; ///< Start address of the multiboot code in memory.
+ std::size_t multiboot_end; ///< End address of the multiboot code in memory.
+ // std::sp
+ // memory_area_container areas; ///< Contains non-owning pointers to all memory areas.
+ };
+
+ /**
+ * @brief Reads the relevant multiboot2 information data from memory.
+ *
+ * @note This is done using the multiboot_information_pointer, which marks the start of the multiboot2 data. The
+ * indivdual headers we have to read are 8 byte aligned, whereas the data contained in those headers does not have to
+ * be. All sections that are read additionaly receive some sanity to ensure the read address is actually pointing to
+ * the expected structure, if they are not this method will assert.
+ *
+ * The memory_information variables are calcualted like this:
+ * - kernel_start: Calculated by getting the lowest address specified in the elf symbols headers.
+ * - kernel_end: Calculated by getting the highest address specified in the elf symbols headers and adding the length
+ * of that section.
+ * - multiboot_start: Calcualted by simply getting the value of the multiboot information pointer, because it already
+ * contains the address pointint to the start of the multiboot2 data.
+ * - multiboot_end: Calcualted by getting the value of the multiboot information pointer and adding the total size of
+ * the complete multiboot2 data
+ * - memory_areas: Calculated by simply accessing the address of the entries variable in the memory map header
+ * structure.
+ * - area_count: Calculated by subtracing the memory map header size from the total tag size, which results in the
+ * remaining size (size of the entries array), this size is then divided by the size of one entry in that array, which
+ * should be 24 bytes.
+ *
+ * @return Relevant data read from multiboot2.
+ */
+ auto read_multiboot2() -> memory_information;
+
+} // namespace teachos::arch::memory::multiboot
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp
new file mode 100644
index 0000000..f68d8b6
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp
@@ -0,0 +1,206 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP
+
+#include "arch/exception_handling/assert.hpp"
+#include "arch/kernel/cpu/tlb.hpp"
+#include "arch/memory/allocator/concept.hpp"
+#include "arch/memory/paging/virtual_page.hpp"
+
+#include <array>
+#include <bitset>
+#include <optional>
+
+namespace teachos::arch::memory::paging
+{
+ /**
+ * @brief Currently actively by the CPU used level 4 page table, is used to ensure there is only ever one valid
+ * instance and it cannot be copied or constructed again.
+ */
+ struct active_page_table
+ {
+ /**
+ * @brief Creates a single instance of an active level 4 page table table and returns the created instance or
+ * alternatively returns the previously created instance instead. The instance is owned by this method and is
+ * static, meaning it lives on for the complete lifetime of the program.
+ *
+ * @return Active single unique instance of the level 4 page table.
+ */
+ static auto create_or_get() -> active_page_table &;
+
+ /**
+ * @brief Index operator overload to access specific mutable entry directy of the level 4 page table.
+ *
+ * @param index Index of the entry we want to access and only read.
+ * @return Entry at the given table index.
+ */
+ auto operator[](std::size_t index) -> entry &;
+
+ /**
+ * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood.
+ *
+ * @param address Virtual address we want to translate into physical one.
+ * @return Physical address corresponding to the provided virtual address.
+ */
+ auto translate_address(virtual_address address) -> std::optional<allocator::physical_address>;
+
+ /**
+ * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if
+ * it failed attempt to parse using huge pages.
+ *
+ * @param page Page to translate into physical frame.
+ * @return Physical frame corresponding to the provided virtual page.
+ */
+ auto translate_page(virtual_page page) -> std::optional<allocator::physical_frame>;
+
+ /**
+ * @brief Translates huge page into actual physical frame.
+ *
+ * @param page Page to translate into physical frame.
+ * @return Physical frame corresponding to the provided virtual page.
+ */
+ auto translate_huge_page(virtual_page page) -> std::optional<allocator::physical_frame>;
+
+ /**
+ * @brief Maps a virtual page to a physical frame in the page table with the specified flags.
+ *
+ * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1
+ * page table already exists it halts execution instead.
+ *
+ * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
+ * deallocate method.
+ * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
+ * entries when a new page table is required.
+ * @param page Virtual page that is being mapped.
+ * @param frame Physical frame that the virtual page will be mapped to.
+ * @param flags A bitset of flags that configure the page table entry for this mapping.
+ */
+ template<allocator::FrameAllocator T>
+ auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags)
+ -> void
+ {
+ auto current_handle = active_handle;
+
+ for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level)
+ {
+ current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level), flags);
+ }
+
+ auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)];
+ arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE),
+ "[Page Mapper] Unable to map huge pages");
+ arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used");
+ level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT);
+ }
+
+ /**
+ * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame.
+ *
+ * @see map_page_to_frame
+ */
+ template<allocator::FrameAllocator T>
+ auto map_page_to_next_free_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void
+ {
+ auto const frame = allocator.allocate_frame();
+ exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception");
+ map_page_to_frame(allocator, page, frame.value(), flags);
+ }
+
+ /**
+ * @brief Gets the corresponding page the given frame has to be contained in and uses that to call
+ * map_page_to_frame.
+ *
+ * @see map_page_to_frame
+ */
+ template<allocator::FrameAllocator T>
+ auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void
+ {
+ auto const page = virtual_page::containing_address(frame.start_address());
+ map_page_to_frame(allocator, page, frame, flags);
+ }
+
+ /**
+ * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags.
+ *
+ * @note For the unmap function to deallocates and unmaps correctly, the entry in every page level if this page was
+ * the last one up to level 4 should be unmapped and ensured to clear the Translation Lookaside Buffer, so that the
+ * unmapped value is removed from cache as well. This is currently not done and instead we only dallocate and unmap
+ * the level 1 page table entry, this is the case because it conflicts with our recursive mapping for the temporary
+ * page, which requires the other page table entries to walk to the actual level 4 page table. If we remove all page
+ * table entries beforehand, we therefore can not remap the kernel anymore.
+ *
+ * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
+ * deallocate method.
+ * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
+ * entries when a new page table is required.
+ * @param page Virtual page that is being unmapped.
+ */
+ template<allocator::FrameAllocator T>
+ auto unmap_page(T & allocator, virtual_page page) -> void
+ {
+ exception_handling::assert(translate_page(page).has_value(),
+ "[Page Mapper] Attempted to unmap page, which has not been mapped previously");
+
+ auto current_handle = active_handle;
+
+ for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level)
+ {
+ auto const level_index = page.get_level_index(level);
+ auto const next_handle = current_handle.next_table(level_index);
+ // The next table method failed even tough the page has to be mapped already, because translate_page did not
+ // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place.
+ exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages");
+ current_handle = next_handle.value();
+ }
+
+ unmap_page_table_entry(allocator, page, current_handle);
+ kernel::cpu::tlb_flush(page.start_address());
+ }
+
+ private:
+ /**
+ * @brief Private constructor should only be used by create or get method, which ensures to create only ever one
+ * instance.
+ *
+ * @param active_handle Handle to the underlying currently active level 4 page table.
+ */
+ active_page_table(page_table_handle active_handle);
+
+ /**
+ * @brief Deleted copy constructor.
+ */
+ active_page_table(active_page_table const &) = delete;
+
+ /**
+ * @brief Deleted copy assignment operator.
+ */
+ active_page_table & operator=(active_page_table const &) = delete;
+
+ /**
+ * @brief Unmaps specific page at the current internal handle level.
+ *
+ * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
+ * deallocate method.
+ * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
+ * entries *when a new page table is required.
+ * @param page Virtual page that is being unmapped.
+ * @param handle Page Table handle we want to access the entry that should be cleared on.
+ */
+ template<allocator::FrameAllocator T>
+ static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void
+ {
+ auto level_index = page.get_level_index(handle.get_level());
+ auto & entry = handle[level_index];
+ auto const frame = entry.calculate_pointed_to_frame();
+ exception_handling::assert(frame.has_value(),
+ "[Page Mapper] Attempted to unmap page, which has not been mapped previously");
+ entry.set_unused();
+ allocator.deallocate_frame(frame.value());
+ }
+
+ public:
+ page_table_handle active_handle; ///< Underlying active level 4 page table
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp
new file mode 100644
index 0000000..8d96740
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp
@@ -0,0 +1,39 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP
+
+#include "arch/memory/allocator/physical_frame.hpp"
+#include "arch/memory/paging/active_page_table.hpp"
+#include "arch/memory/paging/temporary_page.hpp"
+
+namespace teachos::arch::memory::paging
+{
+ /**
+ * @brief By the CPU used level 4 page table.
+ */
+ struct inactive_page_table
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param frame Frame that should be mapped as the level 4 page table.
+ */
+ inactive_page_table(allocator::physical_frame frame);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param frame Frame that should be mapped as the level 4 page table.
+ * @param active_page_table Actual active page table that should be unmapped so we can map a new level 4
+ * page table.
+ * @param temporary_page Temporary page that should be used to map the given frame as the new level 4 page
+ * table.
+ */
+ inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table,
+ temporary_page & temporary_page);
+
+ allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp
new file mode 100644
index 0000000..3afb54b
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp
@@ -0,0 +1,180 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP
+
+#include "arch/kernel/cpu/control_register.hpp"
+#include "arch/memory/paging/active_page_table.hpp"
+#include "arch/memory/paging/inactive_page_table.hpp"
+#include "arch/memory/paging/temporary_page.hpp"
+#include "arch/video/vga/text.hpp"
+
+#include <algorithm>
+#include <array>
+
+namespace teachos::arch::memory::paging
+{
+ /**
+ * @brief Kernel mapper that allows to remap the kernel elf sections in C++.
+ *
+ * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill.
+ */
+ template<allocator::FrameAllocator T>
+ struct kernel_mapper
+ {
+ /**
+ * @brief Constructor.
+ *
+ * @param allocator Allocator that should be used to allocate frames for the remapping process.
+ * @param mem_info Information about elf kernel sections required for remapping process.
+ */
+ kernel_mapper(T & allocator, multiboot::memory_information const & mem_info)
+ : allocator(allocator)
+ , mem_info(mem_info)
+ {
+ // Nothing to do
+ }
+
+ /**
+ * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags
+ * into memory and then replace the created mapping with the current one.
+ *
+ * @note We have to use a workaround with an
+ * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because
+ * remapping active kernel memory in the kernel wouldn't work.
+ */
+ auto remap_kernel() -> void
+ {
+ // Set Page Global Enable bit
+ auto cr4 = kernel::cpu::read_control_register(kernel::cpu::control_register::CR4);
+ kernel::cpu::write_control_register(kernel::cpu::control_register::CR4, cr4 | 0x80);
+
+ temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator};
+ decltype(auto) active_table = active_page_table::create_or_get();
+ auto const frame = allocator.allocate_frame();
+ exception_handling::assert(frame.has_value(),
+ "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped");
+ inactive_page_table new_table{frame.value(), active_table, temporary_page};
+ remap_elf_kernel_sections(new_table, temporary_page, active_table);
+ auto const old_table = switch_active_page_table(new_table);
+ // Turn old level 4 page table, mapped by assembler code into stack guard page.
+ // Only works if the identity mapped page tables by assembler are right above the stack.
+ auto const old_level_4_page =
+ virtual_page::containing_address(old_table.page_table_level_4_frame.start_address());
+ active_table.unmap_page(allocator, old_level_4_page);
+ }
+
+ private:
+ /**
+ * @brief Remaps the kernel elf sections.
+ *
+ * This is done with switching the current level 4 page table recursive
+ * mapping to any unmapped address in memory and then actually mapping the level 4 page table on that address.
+ * Once the remapping process is done we can restore the original recursive mapping with the complete remapped
+ * kernel.
+ *
+ * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we
+ * map the entries.
+ *
+ * @param inactive_table Level 4 page table we temporarily map the kernel into.
+ * @param temporary_page Temporary page that should be used for the mapping process and then
+ * unmapped once finished.
+ * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then
+ * restored once the process is finished.
+ */
+ auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page,
+ active_page_table & active_table) -> void
+ {
+ auto const backup = allocator::physical_frame::containing_address(
+ kernel::cpu::read_control_register(kernel::cpu::control_register::CR3));
+ auto page_table_level4 = temporary_page.map_table_frame(backup, active_table);
+
+ active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE);
+ kernel::cpu::tlb_flush_all();
+ map_elf_kernel_sections(active_table);
+
+ page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE);
+ kernel::cpu::tlb_flush_all();
+ temporary_page.unmap_page(active_table);
+ }
+
+ /**
+ * @brief Switches the current active table pointed to by the CR3 register with another page table that is currently
+ * inactive.
+ *
+ * @param new_table Inactive page table that should now be made active and replace the current active one.
+ * @return The previous active page table.
+ */
+ auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table
+ {
+ auto const backup = allocator::physical_frame::containing_address(
+ kernel::cpu::read_control_register(kernel::cpu::control_register::CR3));
+ auto const old_table = inactive_page_table{backup};
+
+ auto const new_address = new_table.page_table_level_4_frame.start_address();
+ kernel::cpu::write_control_register(kernel::cpu::control_register::CR3, new_address);
+ return old_table;
+ }
+
+ /**
+ * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of
+ * thoose frames gets the correct entry flags according to elf section flags.
+ *
+ * @param active_table Active level 4 page table that should be used to map the required elf sections into entries.
+ * Has had its recursive mapping temporarily replaced and points to unmapped place in memory.
+ */
+ auto map_elf_kernel_sections(active_page_table & active_table) -> void
+ {
+ exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty");
+ std::array<uint64_t, 6U> constexpr USER_SECTION_BASES = {
+ 0x102000, // .boot_bss (Contains statically allocated variables)
+ 0x209000, // .stl_text (Contains code for custom std implementations and standard library code)
+ 0x217000, // .user_text (Contains the actual user code executed)
+ 0x21E000, // .user_data (Contains static user variables)
+
+ 0x20A000 // .text (Necessary, because symbols for all template standard library features are placed here if
+ // they were first used in the Kernel Code Section)
+ };
+
+ for (auto const & section : mem_info.sections)
+ {
+ if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY))
+ {
+ continue;
+ }
+ exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U,
+ "[Kernel Mapper] Section must be page aligned");
+ auto const start_frame = allocator::physical_frame::containing_address(section.physical_address);
+ // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this
+ // section). But end frame would now point to the actual last frame and not one past the last frame, therefore
+ // we increment by one to get one past the last frame of this section.
+ auto const end_frame =
+ ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1));
+
+ allocator::frame_container::iterator const begin{start_frame};
+ allocator::frame_container::iterator const end{end_frame};
+ allocator::frame_container const frames{begin, end};
+ entry entry{section.flags};
+
+ if (std::ranges::find(USER_SECTION_BASES, section.physical_address) != USER_SECTION_BASES.end())
+ {
+ entry.set_user_accessible();
+ }
+
+ for (auto const & frame : frames)
+ {
+ active_table.identity_map(allocator, frame, entry.get_flags());
+ }
+ }
+
+ auto const vga_buffer_frame =
+ allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS);
+ active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE);
+ }
+
+ T & allocator;
+ multiboot::memory_information const &
+ mem_info; ///< Information about elf kernel sections required for remapping process.
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp
new file mode 100644
index 0000000..8147c5c
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp
@@ -0,0 +1,121 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP
+
+#include "arch/memory/allocator/physical_frame.hpp"
+#include "arch/memory/multiboot/elf_symbols_section.hpp"
+
+#include <bitset>
+#include <optional>
+
+namespace teachos::arch::memory::paging
+{
+ /**
+ * @brief Marks a specific entry in an actual page table.
+ */
+ struct entry
+ {
+ /**
+ * @brief Possible set bits in our underlying std::bitset and the meaning when they are set.
+ */
+ enum bitset : uint64_t
+ {
+ PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present.
+ ///< is assumed to be READONLY and only that flag is shown in the objdump.
+ WRITABLE = 1UL << 1UL, ///< It is possible to write to the page.
+ USER_ACCESSIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code.
+ WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache.
+ DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching.
+ ACCESSED = 1UL << 5UL, ///< Page is currently in use.
+ DIRTY = 1UL << 6UL, ///< Page has been writen too.
+ HUGE_PAGE = 1UL << 7UL, ///< Page is huge (2 MiB page size in P2 page table and 1 GiB in P3 page table,
+ ///< instead of 4 KiB). Has to be false for P1 and P4 page tables.
+ GLOBAL = 1UL << 8UL, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register
+ ///< has to be set)
+ EXECUTING_CODE_FORBIDDEN =
+ 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set)
+ };
+
+ /**
+ * @brief Defaulted constructor.
+ */
+ entry() = default;
+
+ /**
+ * @brief Creates a new entry object from a 64bit address. Should follow the scheme where bit index 12 - 51 are the
+ * actual address and the other bits are flags.
+ *
+ * @param flags Flags that will be passed to underlying std::bitset.
+ */
+ explicit entry(uint64_t flags);
+
+ /**
+ * @brief Creates a new entry converting the given elf section flags into the corresponding correct entry flags.
+ *
+ * @note Enables us to set the correct flags on a entry depending on which elf section it is contained in. For
+ * example entries of .text sections should be executable and read only or entries of .data sections should be
+ * writable but not executable.
+ *
+ * @param elf_flags Elf section flags we want to convert into entry flags.
+ */
+ explicit entry(multiboot::elf_section_flags elf_flags);
+
+ /**
+ * @brief Whether the current page is unused, meaning the underlying std::bitset is 0.
+ *
+ * @return Current page is in memory.
+ */
+ auto is_unused() const -> bool;
+
+ /**
+ * @brief Marks the page as unused, meaning the underlying std::bitset is set to 0.
+ */
+ auto set_unused() -> void;
+
+ /**
+ * @brief Marks the page as accessible in User mode, meaning the underlying std::bitset has the 2nd bit aditonally
+ * set.
+ */
+ auto set_user_accessible() -> void;
+
+ /**
+ * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in
+ * memory.
+ *
+ * @return Calculated physical frame entry is pointing too.
+ */
+ auto calculate_pointed_to_frame() const -> std::optional<allocator::physical_frame>;
+
+ /**
+ * @brief Copies the address and flags from the given physical frame into the underlying std::bitset
+ *
+ * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset.
+ * @param additional_flags Entry flags which will be copied into our underlying std::bitset.
+ */
+ auto set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void;
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * std::bitset. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying std::bitset.
+ */
+ auto contains_flags(std::bitset<64U> other) const -> bool;
+
+ /**
+ * @brief Extracts only the flags from the underlying entry and ignores all bits that contain the physical address.
+ *
+ * @return Extracted entry flags, without the physical address.
+ */
+ auto get_flags() const -> std::bitset<64U>;
+
+ private:
+ std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be
+ ///< freely used for additional flags by the operating system.
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp
new file mode 100644
index 0000000..b972337
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp
@@ -0,0 +1,157 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP
+
+#include "arch/exception_handling/assert.hpp"
+#include "arch/memory/allocator/concept.hpp"
+#include "arch/memory/paging/page_entry.hpp"
+
+namespace teachos::arch::memory::paging
+{
+ std::size_t constexpr PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512.
+
+ /**
+ * @brief Forward delcaration of the page_table, because it should only be accessible over the handle.
+ *
+ * @note The actual methods or constructor are not defined meaning they are not callable from outside. Instead the
+ * struct is only fully defined in the implementation (.cpp) file of the page table, and therefore the memthods are
+ * only accesible in that file.
+ */
+ struct page_table;
+
+ /**
+ * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table
+ * method and ensures it can only be called if the table level is not LEVEL1.
+ */
+ struct page_table_handle
+ {
+ /**
+ * @brief Level of the page table.
+ *
+ * Level 1 will not be able to call next_table anymore, because it would result in
+ * attempting to access memory that it should not.
+ */
+ enum level : uint8_t
+ {
+ LEVEL1,
+ LEVEL2,
+ LEVEL3,
+ LEVEL4
+ };
+
+ /**
+ * @brief Constructor.
+ *
+ * @param table Underlying page table the handle should point to.
+ * @param table_level Level the underlying page table is on, used to ensure safety.
+ */
+ page_table_handle(page_table * table, level table_level);
+
+ /**
+ * @brief Set every entry of the page to unused.
+ */
+ auto zero_entries() -> void;
+
+ /**
+ * @brief Checks if all entries of this page are unused.
+ */
+ auto is_empty() const -> bool;
+
+ /**
+ * @brief Get the current table level.
+ *
+ * @return Current table level.
+ */
+ auto get_level() const -> level;
+
+ /**
+ * @brief Returns the next page table level from the given page table index. Meaning we
+ * use an index into a Level 4 page table to get the according Level 3 page table.
+ *
+ * @note If this method is called with a Level 1 page table it will instead assert and halt execution, because there
+ * is no furthere page table and mangeling up and returning the physical address would cause hard to debug issues.
+ *
+ * @param table_index Index of this page table in the page table one level lower.
+ */
+ auto next_table(std::size_t table_index) const -> std::optional<page_table_handle>;
+
+ /**
+ * @brief Call next_table and then checks if the table already exists, if it does not it will use the given
+ * allocator to get the next free frame and set the entry to that instead.
+ *
+ * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
+ * entries when a new page table is required.
+ * @param table_index Index of this page table in the page table one level lower.
+ * @param flags A bitset of flags that configure the page table entry for this mapping.
+ */
+ template<allocator::FrameAllocator T>
+ auto next_table_or_create(T & allocator, std::size_t table_index, std::bitset<64U> flags) -> page_table_handle
+ {
+ auto next_handle = next_table(table_index);
+ // If the next table method failed then it means that the page level of the frame we want allocate has not yet
+ // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done
+ // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a
+ // page table one level below.
+ if (!next_handle.has_value())
+ {
+ auto const allocated_frame = allocator.allocate_frame();
+ exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame");
+ this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE);
+ // There should now be an entry at the previously not existent index, therefore we can simply access it again.
+ next_handle = next_table(table_index);
+ exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table");
+ next_handle.value().zero_entries();
+ }
+
+ // Check if the now created or previously created level 4, level 3 or level 2 page entry is used by user
+ // accessible code. If it is that page entry needs to be user accesible as well.
+ entry entry{flags.to_ulong()};
+ if (entry.contains_flags(entry::USER_ACCESSIBLE))
+ {
+ this->operator[](table_index).set_user_accessible();
+ }
+ return next_handle.value();
+ }
+
+ /**
+ * @brief Index operator overload to access specific mutable entry directy.
+ *
+ * @param index Index of the entry we want to access and only read.
+ * @return Entry at the given table index.
+ */
+ auto operator[](std::size_t index) -> entry &;
+
+ /**
+ * @brief Index operator overload to access specific immutable entry directy.
+ *
+ * @param index Index of the entry we want to access and read or write.
+ * @return Entry at the given table index.
+ */
+ auto operator[](std::size_t index) const -> entry const &;
+
+ /**
+ * @brief Pre decrement operator on the page table level enum, is defined so we can use it as a replacement
+ * for an int index in a range based for loop.
+ *
+ * @note Will halt execution if called with page_table_handle::LEVEL1, because there is no level below. Has to be
+ * defined as either a friend function or inline header method, because we define an operator of another type. In
+ * this instance friend function was choosen, because the struct itself also requires the operator, but declaring
+ * before the struct is not possible, because the enum is in the struct. This is inpossible because the struct
+ * requires the operator declared before itself to work, and the operator requires the struct declared before itself
+ * to work. Furthermore this allows the defintion of the method to be done in the cpp, avoiding includes in the
+ * header file.
+ *
+ * @param value Value we want to decrement on
+ * @return New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ...
+ */
+ friend auto operator--(level & value) -> level &;
+
+ private:
+ page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by
+ ///< constructor)
+ level table_level; ///< Level page table is currently on, depends on how often next_level was
+ ///< called successfuly.
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp
new file mode 100644
index 0000000..d0d7781
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp
@@ -0,0 +1,64 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP
+
+#include "arch/memory/allocator/physical_frame.hpp"
+#include "arch/memory/allocator/tiny_frame_allocator.hpp"
+#include "arch/memory/paging/active_page_table.hpp"
+#include "arch/memory/paging/virtual_page.hpp"
+
+namespace teachos::arch::memory::paging
+{
+ /**
+ * @brief A temporary page used to remap the kernel.
+ */
+ struct temporary_page
+ {
+ /**
+ * @brief Construct a new temporary page object.
+ *
+ * @tparam Type constraint of the allocator, being that is follows the given concept and contains an allocate and
+ * deallocate method.
+ * @param page Page to turn into temporary page.
+ * @param allocator Frame allocator used to fill page.
+ */
+ template<allocator::FrameAllocator T>
+ temporary_page(virtual_page page, T & allocator)
+ : page{page}
+ , allocator{allocator}
+ {
+ // Nothing to do
+ }
+
+ /**
+ * @brief Unmap the current page.
+ *
+ * @param active_table The current active page table.
+ */
+ auto unmap_page(active_page_table & active_table) -> void;
+
+ /**
+ * @brief Map the temporary page to a frame.
+ *
+ * @param frame The frame to which the page is mapped.
+ * @param active_table The current active page table.
+ * @return level1 page table handle containing the mapped page.
+ */
+ auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle;
+
+ private:
+ /**
+ * @brief Map the temporary page to a frame.
+ *
+ * @param frame The frame to which the page is mapped.
+ * @param active_table The current active page table.
+ * @return The virtual address of the page.
+ */
+ auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address;
+
+ virtual_page page; ///< Underlying virtual page we want to temporarily map.
+ allocator::tiny_frame_allocator allocator; ///< Allocator that should be used to map the temporary page.
+ };
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp
new file mode 100644
index 0000000..a6c8c39
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp
@@ -0,0 +1,91 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP
+
+#include "arch/memory/allocator/physical_frame.hpp"
+#include "arch/memory/paging/page_table.hpp"
+
+#include <compare>
+#include <cstdint>
+#include <optional>
+
+namespace teachos::arch::memory::paging
+{
+ using virtual_address = std::size_t;
+
+ /**
+ * @brief Virtual page entry contained in P1 page tables
+ */
+ struct virtual_page
+ {
+ /**
+ * @brief Defaulted constructor.
+ */
+ constexpr virtual_page() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param page_number Index number of the current virtual page, used to distinguish it from other pages.
+ */
+ explicit constexpr virtual_page(std::size_t page_number)
+ : page_number(page_number)
+ {
+ // Nothing to do
+ }
+
+ /**
+ * @brief Returns the virtual page the given address is contained in.
+ *
+ * @param address Virtual address we want to get the corresponding virtual page for.
+ * @return Frame the given address is contained in.
+ */
+ auto static containing_address(virtual_address address) -> virtual_page;
+
+ /**
+ * @brief Evaluates the start address of the virtual page.
+ *
+ * @return Start address of the virtual page.
+ */
+ auto start_address() const -> virtual_address;
+
+ /**
+ * @brief Calculates the index into the page table with the given level, which leads to this virtual page.
+ *
+ * @param level Level of the page table we want to calculate the index for.
+ * @return Index into the page table with the given level.
+ */
+ auto get_level_index(page_table_handle::level level) const -> size_t;
+
+ /**
+ * @brief Post increment operator. Returns a copy of the value.
+ *
+ * @return Copy of the incremented underlying page number.
+ */
+ auto operator++(int) -> virtual_page;
+
+ /**
+ * @brief Pre increment operator. Returns a reference to the changed value.
+ *
+ * @return Reference to the incremented underlying page number.
+ */
+ auto operator++() -> virtual_page &;
+
+ /**
+ * @brief Defaulted equals operator.
+ */
+ auto operator==(const virtual_page & other) const -> bool = default;
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default;
+
+ std::size_t page_number =
+ {}; ///< Index number of the current virtual page, used to distinguish it from other pages.
+ };
+
+ using page_container = stl::container<stl::forward_value_iterator<virtual_page>>;
+
+} // namespace teachos::arch::memory::paging
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP
diff --git a/arch/x86_64/pre/include/arch/user/main.hpp b/arch/x86_64/pre/include/arch/user/main.hpp
new file mode 100644
index 0000000..c168a1f
--- /dev/null
+++ b/arch/x86_64/pre/include/arch/user/main.hpp
@@ -0,0 +1,16 @@
+#ifndef TEACHOS_ARCH_X86_64_USER_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_USER_MAIN_HPP
+
+namespace teachos::arch::user
+{
+ /**
+ * @brief User Main method. If this method finishes there is no code left to run and the whole OS will shut down.
+ * Additionally this main method is executed at Ring 3 and accessing CPU Registers or Kernel level functionality can
+ * only be done over syscalls and not directly anymore.
+ */
+ [[gnu::section(".user_text")]]
+ auto main() -> void;
+
+} // namespace teachos::arch::user
+
+#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP