aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/include
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/include')
-rw-r--r--arch/x86_64/include/arch/boot/pointers.hpp15
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp69
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp81
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp24
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp40
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp45
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp105
-rw-r--r--arch/x86_64/include/arch/context_switching/main.hpp51
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp104
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp93
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp37
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp41
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp73
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp74
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp27
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp32
-rw-r--r--arch/x86_64/include/arch/context_switching/syscall/main.hpp88
-rw-r--r--arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp18
-rw-r--r--arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp18
-rw-r--r--arch/x86_64/include/arch/exception_handling/assert.hpp17
-rw-r--r--arch/x86_64/include/arch/exception_handling/panic.hpp23
-rw-r--r--arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp34
-rw-r--r--arch/x86_64/include/arch/io/port_io.hpp133
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/call.hpp30
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/control_register.hpp71
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/gdtr.hpp27
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/idtr.hpp27
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/if.hpp21
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/msr.hpp64
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/segment_register.hpp97
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/tr.hpp24
-rw-r--r--arch/x86_64/include/arch/kernel/halt.hpp13
-rw-r--r--arch/x86_64/include/arch/kernel/main.hpp13
-rw-r--r--arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp67
-rw-r--r--arch/x86_64/include/arch/memory/allocator/concept.hpp21
-rw-r--r--arch/x86_64/include/arch/memory/allocator/physical_frame.hpp86
-rw-r--r--arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp74
-rw-r--r--arch/x86_64/include/arch/memory/heap/bump_allocator.hpp48
-rw-r--r--arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp118
-rw-r--r--arch/x86_64/include/arch/memory/heap/heap_allocator.hpp45
-rw-r--r--arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp119
-rw-r--r--arch/x86_64/include/arch/memory/heap/memory_block.hpp39
-rw-r--r--arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp148
-rw-r--r--arch/x86_64/include/arch/memory/main.hpp30
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp169
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/info.hpp64
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/memory_map.hpp53
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/reader.hpp53
-rw-r--r--arch/x86_64/include/arch/memory/paging/active_page_table.hpp206
-rw-r--r--arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp39
-rw-r--r--arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp180
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_entry.hpp121
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_table.hpp157
-rw-r--r--arch/x86_64/include/arch/memory/paging/temporary_page.hpp64
-rw-r--r--arch/x86_64/include/arch/memory/paging/virtual_page.hpp91
-rw-r--r--arch/x86_64/include/arch/stl/container.hpp99
-rw-r--r--arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp216
-rw-r--r--arch/x86_64/include/arch/stl/forward_value_iterator.hpp121
-rw-r--r--arch/x86_64/include/arch/stl/mutex.hpp60
-rw-r--r--arch/x86_64/include/arch/stl/shared_pointer.hpp269
-rw-r--r--arch/x86_64/include/arch/stl/stack.hpp212
-rw-r--r--arch/x86_64/include/arch/stl/unique_pointer.hpp204
-rw-r--r--arch/x86_64/include/arch/stl/vector.hpp601
-rw-r--r--arch/x86_64/include/arch/user/main.hpp16
-rw-r--r--arch/x86_64/include/arch/video/vga/io.hpp39
-rw-r--r--arch/x86_64/include/arch/video/vga/text.hpp169
-rw-r--r--arch/x86_64/include/x86_64/boot/boot.hpp70
-rw-r--r--arch/x86_64/include/x86_64/boot/ld.hpp61
-rw-r--r--arch/x86_64/include/x86_64/cpu/control_register.hpp244
-rw-r--r--arch/x86_64/include/x86_64/cpu/model_specific_register.hpp148
-rw-r--r--arch/x86_64/include/x86_64/cpu/registers.hpp30
-rw-r--r--arch/x86_64/include/x86_64/device_io/port_io.hpp101
-rw-r--r--arch/x86_64/include/x86_64/memory/buffered_allocator.hpp68
-rw-r--r--arch/x86_64/include/x86_64/memory/kernel_mapper.hpp32
-rw-r--r--arch/x86_64/include/x86_64/memory/mmu.hpp (renamed from arch/x86_64/include/arch/kernel/cpu/tlb.hpp)14
-rw-r--r--arch/x86_64/include/x86_64/memory/page_table.hpp341
-rw-r--r--arch/x86_64/include/x86_64/memory/page_utilities.hpp22
-rw-r--r--arch/x86_64/include/x86_64/memory/paging_root.hpp27
-rw-r--r--arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp23
-rw-r--r--arch/x86_64/include/x86_64/memory/region_allocator.hpp79
-rw-r--r--arch/x86_64/include/x86_64/memory/scoped_mapping.hpp66
-rw-r--r--arch/x86_64/include/x86_64/vga/crtc.hpp39
-rw-r--r--arch/x86_64/include/x86_64/vga/text.hpp178
83 files changed, 1536 insertions, 5634 deletions
diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp
deleted file mode 100644
index fe9c657..0000000
--- a/arch/x86_64/include/arch/boot/pointers.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP
-#define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP
-
-#include <cstddef>
-
-namespace teachos::arch::boot
-{
- /**
- * @brief Address pointing to the start of the multiboot information structure.
- */
- extern "C" size_t const multiboot_information_pointer;
-
-} // namespace teachos::arch::boot
-
-#endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP
diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
deleted file mode 100644
index 07110c8..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#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/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
deleted file mode 100644
index 5104c36..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#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/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
deleted file mode 100644
index b388e0e..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#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/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
deleted file mode 100644
index 7fe933b..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#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/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
deleted file mode 100644
index e45bcf4..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#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/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
deleted file mode 100644
index 2a7704e..0000000
--- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#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/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp
deleted file mode 100644
index f8477ea..0000000
--- a/arch/x86_64/include/arch/context_switching/main.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
deleted file mode 100644
index 7450330..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
+++ /dev/null
@@ -1,104 +0,0 @@
-
-#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/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp
deleted file mode 100644
index e24b988..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp
deleted file mode 100644
index 44f2692..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp
deleted file mode 100644
index 292ff70..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp
deleted file mode 100644
index 933fb4d..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp
+++ /dev/null
@@ -1,73 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp
deleted file mode 100644
index 40bcc8a..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp
deleted file mode 100644
index 8770b81..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#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/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp
deleted file mode 100644
index d4aa5e8..0000000
--- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#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/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp
deleted file mode 100644
index 59adc13..0000000
--- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#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/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp
deleted file mode 100644
index 8cb468a..0000000
--- a/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#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/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp
deleted file mode 100644
index 2e7bcd1..0000000
--- a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#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/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp
deleted file mode 100644
index 1286768..0000000
--- a/arch/x86_64/include/arch/exception_handling/assert.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#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/include/arch/exception_handling/panic.hpp b/arch/x86_64/include/arch/exception_handling/panic.hpp
deleted file mode 100644
index 6a2404c..0000000
--- a/arch/x86_64/include/arch/exception_handling/panic.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#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/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp
deleted file mode 100644
index 15b35c1..0000000
--- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#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/include/arch/io/port_io.hpp b/arch/x86_64/include/arch/io/port_io.hpp
deleted file mode 100644
index ba41660..0000000
--- a/arch/x86_64/include/arch/io/port_io.hpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP
-#define TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP
-
-#include <concepts>
-#include <cstddef>
-#include <cstdint>
-#include <type_traits>
-
-namespace teachos::arch::io
-{
- /**
- * @brief An I/O port of a given size at a given address.
- *
- * @tparam Address The address (port number) of the I/O port.
- * @tparam Size The size (in bytes) of the I/O port.
- */
- template<std::uint16_t Address, std::size_t Size>
- struct port
- {
- static_assert(Size == 1 || Size == 2 || Size == 4, "A port must be either 1, 2, or 4 bytes in size");
-
- /**
- * @brief The type of data available for reading and writing through this port.
- */
- using io_type =
- std::conditional_t<Size == 1, std::byte, std::conditional_t<Size == 2, std::uint16_t, std::uint32_t>>;
-
- /**
- * @brief Write a byte to the I/O port.
- *
- * @param data The data to write to the I/O port.
- */
- auto static write(io_type data) -> void
- requires(Size == 1)
- {
- asm volatile("mov %[port], %%dx\n"
- "mov %[data], %%al\n"
- "out %%al, %%dx\n"
- :
- : [port] "i"(Address), [data] "im"(data)
- : "dx", "al");
- }
-
- /**
- * @brief Write a word to the I/O port.
- *
- * @param data The data to write to the I/O port.
- */
- auto static write(io_type data) -> void
- requires(Size == 2)
- {
- asm volatile("mov %[port], %%dx\n"
- "mov %[data], %%ax\n"
- "out %%ax, %%dx\n"
- :
- : [port] "i"(Address), [data] "im"(data)
- : "dx", "ax");
- }
-
- /**
- * @brief Write a double-word to the I/O port.
- *
- * @param data The data to write to the I/O port.
- */
- auto static write(io_type data) -> void
- requires(Size == 4)
- {
- asm volatile("mov %[port], %%dx\n"
- "mov %[data], %%eax\n"
- "out %%eax, %%dx\n"
- :
- : [port] "i"(Address), [data] "im"(data)
- : "dx", "eax");
- }
-
- /**
- * @brief Read a byte from the I/O port.
- *
- * @return The data read from the I/O port.
- */
- auto static read() -> io_type
- requires(Size == 1)
- {
- auto data = io_type{};
- asm volatile("mov %[port], %%dx\n"
- "in %%dx, %%al\n"
- "mov %%al, %[data]\n"
- : [data] "=m"(data)
- : [port] "i"(Address)
- : "dx", "al");
- return data;
- }
-
- /**
- * @brief Read a word from the I/O port.
- *
- * @return The data read from the I/O port.
- */
- auto static read() -> io_type
- requires(Size == 2)
- {
- auto data = io_type{};
- asm volatile("mov %[port], %%dx\n"
- "in %%dx, %%ax\n"
- "mov %%ax, %[data]\n"
- : [data] "=m"(data)
- : [port] "i"(Address)
- : "dx", "ax");
- return data;
- }
-
- /**
- * @brief Read a double-word from the I/O port.
- *
- * @return The data read from the I/O port.
- */
- auto static read() -> io_type
- requires(Size == 4)
- {
- auto data = io_type{};
- asm volatile("mov %[port], %%dx\n"
- "in %%dx, %%eax\n"
- "mov %%eax, %[data]\n"
- : [data] "=m"(data)
- : [port] "i"(Address)
- : "dx", "eax");
- return data;
- }
- };
-
-} // namespace teachos::arch::io
-
-#endif // TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP
diff --git a/arch/x86_64/include/arch/kernel/cpu/call.hpp b/arch/x86_64/include/arch/kernel/cpu/call.hpp
deleted file mode 100644
index 3c43304..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/call.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#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/include/arch/kernel/cpu/control_register.hpp b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp
deleted file mode 100644
index dcaf02d..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP
-
-#include <cstdint>
-
-namespace teachos::arch::kernel::cpu
-{
- /**
- * @brief Control registers that can be read and written to.
- *
- * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined
- * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more
- * information.
- */
- enum struct control_register : uint8_t
- {
- CR0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW)
- ///< register.
- CR2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces
- ///< is stored here.
- CR3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging
- ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the
- ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level
- ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be
- ///< first translated into a physical address.
- CR4 ///< Used in protected mode to control operations.
- };
-
- /**
- * @brief Control register 0 flags that can be set.
- *
- * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest
- * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information.
- */
- enum struct cr0_flags : uint64_t
- {
- PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode.
- TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used.
- WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0.
- PAGING = 1U << 31U, // Enable paging using the CR3 register.
- };
-
- /**
- * @brief Reads the value of the given control register.
- *
- * @param cr Control register that should be read.
- * @return Value of the control register.
- */
- auto read_control_register(control_register cr) -> uint64_t;
-
- /**
- * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register.
- *
- * @param cr Control register that should be written.
- * @param new_value New value that should be written.
- */
- auto write_control_register(control_register cr, uint64_t new_value) -> void;
-
- /**
- * @brief Sets a specific bit in the CR0.
- *
- * @note This function reads the current value of the CR0 register, ORs the specified
- * bit with the current value, and writes the updated value back to the CR0.
- *
- * @param flag he flag to set in the CR0.
- */
- auto set_cr0_bit(cr0_flags flag) -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP
diff --git a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp
deleted file mode 100644
index 68b950d..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#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/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp
deleted file mode 100644
index cb800d0..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#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/include/arch/kernel/cpu/if.hpp b/arch/x86_64/include/arch/kernel/cpu/if.hpp
deleted file mode 100644
index 48707dc..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/if.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#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/include/arch/kernel/cpu/msr.hpp b/arch/x86_64/include/arch/kernel/cpu/msr.hpp
deleted file mode 100644
index 99d6378..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/msr.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#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/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp
deleted file mode 100644
index a236452..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#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/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/include/arch/kernel/cpu/tr.hpp
deleted file mode 100644
index 7c856f1..0000000
--- a/arch/x86_64/include/arch/kernel/cpu/tr.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#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/include/arch/kernel/halt.hpp b/arch/x86_64/include/arch/kernel/halt.hpp
deleted file mode 100644
index 377acc0..0000000
--- a/arch/x86_64/include/arch/kernel/halt.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#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/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp
deleted file mode 100644
index a13e5f4..0000000
--- a/arch/x86_64/include/arch/kernel/main.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#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/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp
deleted file mode 100644
index 6cb5f56..0000000
--- a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
-
-#include "arch/memory/allocator/physical_frame.hpp"
-#include "arch/memory/multiboot/reader.hpp"
-
-#include <optional>
-
-namespace teachos::arch::memory::allocator
-{
- /**
- * @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 teachos::arch::memory::allocator
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp
deleted file mode 100644
index 2d3f4ae..0000000
--- a/arch/x86_64/include/arch/memory/allocator/concept.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#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/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp
deleted file mode 100644
index cb6c5b3..0000000
--- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP
-
-#include "arch/stl/container.hpp"
-#include "arch/stl/forward_value_iterator.hpp"
-
-#include <compare>
-#include <cstdint>
-#include <iterator>
-
-namespace teachos::arch::memory::allocator
-{
- using physical_address = std::size_t;
-
- std::size_t constexpr PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB.
-
- /**
- * @brief Specific physical frame containing helper functions to determine if a specific address is in that
- * physical frame or not.
- */
- struct physical_frame
- {
- /**
- * @brief Defaulted constructor.
- */
- constexpr physical_frame() = default;
-
- /**
- * @brief Constructor.
- *
- * @param frame_number Index number that should be assigned to this physical frame.
- */
- explicit constexpr physical_frame(std::size_t frame_number)
- : frame_number(frame_number)
- {
- // Nothing to do
- }
-
- /**
- * @brief Returns the physical frame the given address is contained in.
- *
- * @param address Physical address we want to get the corresponding physical frame for.
- * @return Frame the given address is contained in.
- */
- auto static containing_address(physical_address address) -> physical_frame;
-
- /**
- * @brief Get the start address of this physical frame.
- *
- * @return Start address of the physical frame.
- */
- auto start_address() const -> physical_address;
-
- /**
- * @brief Post increment operator. Returns a copy of the value.
- *
- * @return Copy of the incremented underlying frame number.
- */
- auto operator++(int) -> physical_frame;
-
- /**
- * @brief Pre increment operator. Returns a reference to the changed value.
- *
- * @return Reference to the incremented underlying frame number.
- */
- auto operator++() -> physical_frame &;
-
- /**
- * @brief Defaulted equals operator.
- */
- auto operator==(physical_frame const & other) const -> bool = default;
-
- /**
- * @brief Defaulted three-way comparsion operator.
- */
- auto operator<=>(physical_frame const & other) const -> std::partial_ordering = default;
-
- std::size_t frame_number =
- {}; ///< Index number of the current physical frame, used to distinguish it from other frames.
- };
-
- using frame_container = stl::container<stl::forward_value_iterator<physical_frame>>;
-
-} // namespace teachos::arch::memory::allocator
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP
diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp
deleted file mode 100644
index 1ceb74d..0000000
--- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#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/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp
deleted file mode 100644
index 011f45c..0000000
--- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#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/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp
deleted file mode 100644
index c98c130..0000000
--- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#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/include/arch/memory/heap/heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp
deleted file mode 100644
index 420a1d3..0000000
--- a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#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/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp
deleted file mode 100644
index 582b4af..0000000
--- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#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 "arch/stl/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.
- stl::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/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp
deleted file mode 100644
index 9d1fb02..0000000
--- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#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/include/arch/memory/heap/user_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp
deleted file mode 100644
index 6b1b7bb..0000000
--- a/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp
+++ /dev/null
@@ -1,148 +0,0 @@
-#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 "arch/stl/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.
- stl::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/include/arch/memory/main.hpp b/arch/x86_64/include/arch/memory/main.hpp
deleted file mode 100644
index d51815f..0000000
--- a/arch/x86_64/include/arch/memory/main.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#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/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp
deleted file mode 100644
index 0a25ca9..0000000
--- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp
+++ /dev/null
@@ -1,169 +0,0 @@
-#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/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp
deleted file mode 100644
index a9abf12..0000000
--- a/arch/x86_64/include/arch/memory/multiboot/info.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
-
-#include <cstdint>
-
-namespace teachos::arch::memory::multiboot
-{
- /**
- * @brief Defines all possible types a multiboot2 tag structure can have.
- *
- * @note See
- * https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot2.h for more information on the structure of the
- * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the
- * actual header contents and their following data.
- */
- enum struct tag_type : uint32_t
- {
- END, ///< Signals final tag for the multiboot2 information structure.
- CMDLINE, ///< Contains the command line string.
- BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel.
- MODULE, ///< Indicates the boot module which was loaded along the kernel image.
- BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address).
- BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from.
- MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags.
- VBE_INFO, ///< Includes information to access and utilize the device GPU.
- FRAMEBUFFER, ///< VBE framebuffer information.
- ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel.
- APM_INFO, ///< Advanced Power Management information.
- EFI32, ///< EFI 32 bit system table pointer.
- EFI64, ///< EFI 64 bit system table pointer.
- SMBIOS, ///< Contains copy of all Sytem Management BIOS tables.
- ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification.
- ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification.
- NETWORK, ///< Contains network information specified specified as DHCP.
- EFI_MEMORY_MAP, ///< Contains EFI memory map.
- EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called.
- EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer.
- EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer.
- LOAD_BASE_ADDRESS ///< Contains image load base physical address.
- };
-
- /**
- * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin
- * with.
- */
- struct tag
- {
- tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling.
- uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type.
- };
-
- /**
- * @brief Basic structure the multiboot_information_pointer points too and which contains all information of
- * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned.
- */
- struct info_header
- {
- uint32_t total_size; ///< Total size of all multiboot::tags and their data.
- alignas(8) struct tag tags; ///< Specific tags.
- };
-
-} // namespace teachos::arch::memory::multiboot
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP
diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp
deleted file mode 100644
index 68394c8..0000000
--- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
-
-#include "arch/memory/multiboot/info.hpp"
-#include "arch/stl/container.hpp"
-#include "arch/stl/contiguous_pointer_iterator.hpp"
-
-#include <cstdint>
-
-namespace teachos::arch::memory::multiboot
-{
- /**
- * @brief Defines all memory area types possible that the memory region can be in.
- */
- enum struct memory_area_type : uint32_t
- {
- AVAILABLE = 1, ///< Region is available for use by the OS.
- RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS.
- ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event.
- RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS).
- DEFECTIVE ///< Region is defective or unusable.
- };
-
- /**
- * @brief Defines an entry in the entries array of the memory_map struct.
- *
- * @note Last value needs to be padded, because the size of the entry needs to be
- * exactly 24 bytes and not one byte more.
- */
- struct memory_area
- {
- uint64_t base_address; ///< Base address the memory region starts at.
- uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address.
- alignas(8) memory_area_type type; ///< Specific type of memory the region can contain.
- };
-
- /**
- * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
- * multi_boot_tag_type::MEMORY_MAP.
- */
- struct memory_map_header
- {
- tag info; ///< Basic multi_boot_tag information.
- uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8.
- uint32_t entry_version; ///< Version of the entries, currently 0.
- struct memory_area entries; ///< Specific memory regions.
- };
-
- using memory_area_container = stl::container<stl::contiguous_pointer_iterator<memory_area>>;
-
-} // namespace teachos::arch::memory::multiboot
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP
diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp
deleted file mode 100644
index bda0c43..0000000
--- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#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 <cstdint>
-
-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.
- elf_section_header_container sections; ///< 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.
- 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/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp
deleted file mode 100644
index f68d8b6..0000000
--- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp
+++ /dev/null
@@ -1,206 +0,0 @@
-#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/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp
deleted file mode 100644
index 8d96740..0000000
--- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#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/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp
deleted file mode 100644
index 81ac0cb..0000000
--- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp
+++ /dev/null
@@ -1,180 +0,0 @@
-#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)
- 0x218000, // .user_text (Contains the actual user code executed)
- 0x21F000, // .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/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp
deleted file mode 100644
index 8147c5c..0000000
--- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#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/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp
deleted file mode 100644
index b972337..0000000
--- a/arch/x86_64/include/arch/memory/paging/page_table.hpp
+++ /dev/null
@@ -1,157 +0,0 @@
-#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/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp
deleted file mode 100644
index d0d7781..0000000
--- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#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/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp
deleted file mode 100644
index a6c8c39..0000000
--- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#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/include/arch/stl/container.hpp b/arch/x86_64/include/arch/stl/container.hpp
deleted file mode 100644
index 4ea08c7..0000000
--- a/arch/x86_64/include/arch/stl/container.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP
-#define TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP
-
-#include <iterator>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Minimal iterator concept required for usage in container
- */
- template<typename T>
- concept Iterator = std::forward_iterator<T>;
-
- /**
- * @brief Read-only container for given template type, that allow to easily use this container instance in C++20
- * ranges calls.
- *
- * @tparam T Iterator the container uses to signal the start and end of it's data, has to atleast be a simple forward
- * iterator.
- */
- template<Iterator T>
- struct container
- {
- using iterator = T; ///< Iterators used by this container.
- using size_type = std::size_t; ///< Maximum size of this container.
-
- /**
- * @brief Defaulted constructor.
- */
- container() = default;
-
- /**
- * @brief Constructor.
- *
- * @param begin Iterator containing non-owning pointer to the first element of all memory areas.
- * @param end Iterator pointing to one past the last element of all memory areas.
- */
- container(iterator begin, iterator end)
- : begin_itr(begin)
- , end_itr(end)
- {
- // Nothing to do
- }
-
- /**
- * @brief Returns the iterator pointing to the first element of the memory area.
- * Allows using this class in the for each loop, because it follows the InputIterator template scheme.
- *
- * @return Iterator pointing to first element of the memory area.
- */
- [[gnu::section(".stl_text")]]
- auto begin() const -> iterator
- {
- return begin_itr;
- }
-
- /**
- * @brief Returns the iterator pointing to one past the last element of the memory area.
- * Allows using this class in the for each loop, because it follows the InputIterator template scheme.
- *
- * @return Iterator pointing to one past the last element of the memory area.
- */
- [[gnu::section(".stl_text")]]
- auto end() const -> iterator
- {
- return end_itr;
- }
-
- /**
- * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the
- * last.
- *
- * @return Actual size of this container.
- */
- [[gnu::section(".stl_text")]]
- auto size() const -> size_type
- {
- return std::distance(begin(), end());
- }
-
- /**
- * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy.
- *
- * @return Whether the container is empty, size being 0 or not
- */
- [[gnu::section(".stl_text")]]
- auto empty() const -> bool
- {
- return size() == 0;
- }
-
- private:
- iterator begin_itr = {}; ///< Pointer to the first element of the given template type.
- iterator end_itr = {}; ///< Pointer to one pas the last element of the given template type.
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP
diff --git a/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp
deleted file mode 100644
index f2dfb2b..0000000
--- a/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp
+++ /dev/null
@@ -1,216 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP
-#define TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP
-
-#include <iterator>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Generic contiguous iterator for given template type. Allows to easily use this iterator instance in
- * algorithm calls.
- *
- * @note Allows any value that is contained in an array in memory, which is a block of contiguous memory. This is the
- * case because we assume we can simply increment or decrement the pointer address to get the next valid instance of
- * the given value type.
- *
- * @tparam T Value the iterator points too.
- */
- template<typename T>
- struct contiguous_pointer_iterator
- {
- using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type.
- using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another.
- using value_type = T; ///< Underlying value pointed to by this iterator.
- using reference_type = value_type &; ///< Reference to value returned by dereference * operation.
- using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation.
-
- /**
- * @brief Defaulted constructor.
- */
- contiguous_pointer_iterator() = default;
-
- /**
- * @brief Constructor.
- *
- * @param p Underlying address the iterator should point too.
- */
- explicit contiguous_pointer_iterator(value_type * p)
- : ptr(p)
- {
- // Nothing to do
- }
-
- /**
- * @brief Dereferences the initally given pointer to its value.
- *
- * @return Reference to the value.
- */
- [[gnu::section(".stl_text")]]
- auto operator*() const -> reference_type
- {
- return *ptr;
- }
-
- /**
- * @brief Get underlying value, which is the intially passed pointer.
- *
- * @return Pointer to the underlying value passed intially.
- */
- [[gnu::section(".stl_text")]]
- auto operator->() const -> pointer_type
- {
- return ptr;
- }
-
- /**
- * @brief Pre decrement operator. Returns a reference to the changed address.
- *
- * @return Reference to the decremented underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator--() -> contiguous_pointer_iterator &
- {
- contiguous_pointer_iterator const old_value = *this;
- ++ptr;
- return old_value;
- }
-
- /**
- * @brief Pre increment operator. Returns a reference to the changed address.
- *
- * @return Reference to the incremented underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator++() -> contiguous_pointer_iterator &
- {
- ++ptr;
- return *this;
- }
-
- /**
- * @brief Post decrement operator. Returns a copy of the address.
- *
- * @return Copy of the decremented underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator--(int) -> contiguous_pointer_iterator
- {
- auto const old_value = *this;
- --ptr;
- return old_value;
- }
-
- /**
- * @brief Post increment operator. Returns a copy of the address.
- *
- * @return Copy of the incremented underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator++(int) -> contiguous_pointer_iterator
- {
- auto const old_value = *this;
- ++ptr;
- return old_value;
- }
-
- /**
- * @brief Addition assignment operator. Returns a reference to the changed address.
- *
- * @param value Value we want to add to the underlying address.
- * @return Reference to the changed underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator+=(difference_type value) -> contiguous_pointer_iterator &
- {
- ptr += value;
- return *this;
- }
-
- /**
- * @brief Subtraction assignment operator. Returns a reference to the changed address.
- *
- * @param value Value we want to subtract from the underlying address.
- * @return Reference to the changed underlying address.
- */
- [[gnu::section(".stl_text")]]
- auto operator-=(difference_type value) -> contiguous_pointer_iterator &
- {
- ptr -= value;
- return *this;
- }
-
- /**
- * @brief Addition operator. Returns the changed address.
- *
- * @param value Value we want to add to a copy of the underlying address.
- * @return Copy of underlying address incremented by the given value.
- */
- [[gnu::section(".stl_text")]]
- auto operator+(difference_type value) const -> contiguous_pointer_iterator
- {
- return contiguous_pointer_iterator{ptr + value};
- }
-
- /**
- * @brief Subtraction operator. Returns the changed address.
- *
- * @param value Value we want to subtrcat from a copy of the underlying address.
- * @return Copy of underlying address decremented by the given value.
- */
- [[gnu::section(".stl_text")]]
- auto operator-(difference_type value) const -> contiguous_pointer_iterator
- {
- return contiguous_pointer_iterator{ptr - value};
- }
-
- /**
- * @brief Subtraction operator. Returns the size difference between two iterators.
- *
- * @param other Other iterator we want to substract the underlying address with ours.
- * @return Size difference between the underlying address of this instance and the given iterator.
- */
- [[gnu::section(".stl_text")]]
- auto operator-(const contiguous_pointer_iterator & other) const -> difference_type
- {
- return ptr - other.ptr;
- }
-
- /**
- * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the
- * dereferenced underlying pointer incremented by the given index.
- *
- * @param index Index we want to access and get the value from.
- * @return Reference to the value at the given index.
- */
- [[gnu::section(".stl_text")]]
- auto operator[](difference_type index) const -> value_type &
- {
- return *(ptr + index);
- }
-
- /**
- * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators.
- *
- * @param other Other iterator to compare to.
- * @return Whether both iterators point to the same underlying address in memory.
- */
- [[gnu::section(".stl_text")]]
- auto operator==(contiguous_pointer_iterator const & other) const -> bool = default;
-
- /**
- * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators.
- *
- * @param other Other iterator to compare to.
- * @return Whether the given iterator is smaller or larger than this iterator.
- */
- [[gnu::section(".stl_text")]]
- auto operator<=>(contiguous_pointer_iterator const & other) const -> std::strong_ordering = default;
-
- private:
- pointer_type ptr =
- {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement.
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP
diff --git a/arch/x86_64/include/arch/stl/forward_value_iterator.hpp b/arch/x86_64/include/arch/stl/forward_value_iterator.hpp
deleted file mode 100644
index be3d8e6..0000000
--- a/arch/x86_64/include/arch/stl/forward_value_iterator.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP
-#define TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP
-
-#include <iterator>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Concept for a type to have a post and prefix increment operator, that returns the correct type.
- */
- template<typename T>
- concept Incrementable = requires(T t) {
- { ++t } -> std::same_as<T &>;
- { t++ } -> std::same_as<T>;
- };
-
- /**
- * @brief Iterable concept for the forward value iterator, meaning the type itself is incrementable and comparable.
- */
- template<typename T>
- concept Iterable = std::regular<T> && Incrementable<T>;
-
- /**
- * @brief Generic forward iterator for given template type. Allows to easily use this iterator
- * instance in algorithm calls.
- *
- * @note Allows any value that itself can be incremented until we have reached the end, does not interact with the
- * address of the value in any way.
- *
- * @tparam T Value the iterator contains.
- */
- template<Iterable T>
- struct forward_value_iterator
- {
- using iterator_category = std::forward_iterator_tag; ///< Iterator category of this type.
- using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another.
- using value_type = T; ///< Underlying value contained by this iterator.
- using const_reference_type =
- value_type const &; ///< Constant reference to value returned by dereference * operation.
- using const_pointer_type = value_type const *; ///< Constant pointer to value returned by arrow -> operation.
-
- /**
- * @brief Defaulted constructor.
- */
- forward_value_iterator() = default;
-
- /**
- * @brief Constructor.
- *
- * @param value Underlying value the iterator contains.
- */
- explicit forward_value_iterator(value_type value)
- : value(value)
- {
- // Nothing to do
- }
-
- /**
- * @brief Returns the initally given value.
- *
- * @return Reference to the value.
- */
- [[gnu::section(".stl_text")]]
- auto operator*() const -> const_reference_type
- {
- return value;
- }
-
- /**
- * @brief Gets pointer to the underlying value passed intially.
- *
- * @return Pointer to the underlying value passed intially.
- */
- [[gnu::section(".stl_text")]]
- auto operator->() const -> const_pointer_type
- {
- return &value;
- }
-
- /**
- * @brief Pre increment operator. Returns a reference to the changed value.
- *
- * @return Reference to the incremented underlying value.
- */
- [[gnu::section(".stl_text")]]
- auto operator++() -> forward_value_iterator &
- {
- ++value;
- return *this;
- }
-
- /**
- * @brief Post increment operator. Returns a copy of the value.
- *
- * @return Copy of the incremented underlying value.
- */
- [[gnu::section(".stl_text")]]
- auto operator++(int) -> forward_value_iterator
- {
- auto const old_value = *this;
- ++value;
- return old_value;
- }
-
- /**
- * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators.
- *
- * @param other Other iterator to compare to.
- * @return Whether both iterators point to the same underlying address in memory.
- */
- [[gnu::section(".stl_text")]]
- auto operator==(forward_value_iterator const & other) const -> bool = default;
-
- private:
- value_type value =
- {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement.
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP
diff --git a/arch/x86_64/include/arch/stl/mutex.hpp b/arch/x86_64/include/arch/stl/mutex.hpp
deleted file mode 100644
index a7d297d..0000000
--- a/arch/x86_64/include/arch/stl/mutex.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_MUTEX_HPP
-#define TEACHOS_ARCH_X86_64_STL_MUTEX_HPP
-
-#include <atomic>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in
- * use by another thread or not.
- */
- struct mutex
- {
- /**
- * @brief Defaulted constructor.
- */
- mutex() = default;
-
- /**
- * @brief Defaulted destructor.
- */
- ~mutex() = default;
-
- /**
- * @brief Deleted copy constructor.
- */
- mutex(const mutex &) = delete;
-
- /**
- * @brief Deleted assignment operator.
- */
- mutex & operator=(const mutex &) = delete;
-
- /**
- * @brief Lock the mutex (blocks for as long as it is not available).
- */
- [[gnu::section(".stl_text")]]
- auto lock() -> void;
-
- /**
- * @brief Try to lock the mutex (non-blocking).
- *
- * @return True if lock has been acquired and false otherwise.
- */
- [[gnu::section(".stl_text")]]
- auto try_lock() -> bool;
-
- /**
- * @brief Unlock the mutex.
- */
- [[gnu::section(".stl_text")]]
- auto unlock() -> void;
-
- private:
- std::atomic<bool> locked = {false}; // Atomic boolean to track if mutex is locked or not.
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_MUTEX_HPP
diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp
deleted file mode 100644
index c9796a8..0000000
--- a/arch/x86_64/include/arch/stl/shared_pointer.hpp
+++ /dev/null
@@ -1,269 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP
-#define TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP
-
-#include <atomic>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several
- * shared_pointer objects may own the same object. The object is destroyed and its memory deallocated when either of
- * the following happens: the last remaining shared_pointer owning the object is destroyed; the last remaining
- * shared_pointer owning the object is assigned another pointer via operator= or reset(). A
- * shared_pointer can share ownership of an object while storing a pointer to another object. This feature can be used
- * to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(),
- * the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count
- * reaches zero.
- *
- * @tparam T The type of the managed object.
- */
- template<typename T>
- struct shared_pointer
- {
- /**
- * @brief Constructor.
- *
- * @param pointer A pointer to an object to manage (default is nullptr).
- */
- [[gnu::section(".stl_text")]]
- explicit shared_pointer(T * pointer = nullptr)
- : pointer(pointer)
- , ref_count(new std::atomic<std::size_t>(pointer != nullptr ? 1 : 0))
- {
- // Nothing to do.
- }
-
- /**
- * @brief Copy constructor.
- *
- * @param other The shared_pointer to copy from.
- */
- [[gnu::section(".stl_text")]]
- shared_pointer(const shared_pointer & other)
- : pointer(other.pointer)
- , ref_count(other.ref_count)
- {
- if (pointer != nullptr)
- {
- ++(*ref_count);
- }
- }
-
- /**
- * @brief Move constructor.
- *
- * @param other The shared_pointer to move from.
- */
- [[gnu::section(".stl_text")]]
- shared_pointer(shared_pointer && other) noexcept
- : pointer(other.pointer)
- , ref_count(other.ref_count)
- {
- other.pointer = nullptr;
- other.ref_count = nullptr;
- }
-
- /**
- * @brief Copy assignment operator. Replaces the managed object with the one managed by r. Shares ownership of the
- * object managed by r. If r manages no object, *this manages no object too. Equivalent to
- * shared_ptr<T>(r).swap(*this).
- *
- * @param other Another smart pointer to share the ownership with.
- * @return Reference to this shared pointer.
- */
- [[gnu::section(".stl_text")]]
- shared_pointer & operator=(const shared_pointer & other)
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- ref_count = other.ref_count;
-
- if (pointer != nullptr)
- {
- ++(*ref_count);
- }
- }
-
- return *this;
- }
-
- /**
- * @brief Move assignment operator. Move-assigns a shared_ptr from r. After the assignment, *this contains a copy of
- * the previous state of r, and r is empty. Equivalent to shared_ptr<T>(std::move(r)).swap(*this).
- *
- * @param other Another smart pointer to acquire the ownership from.
- * @return Reference to this shared pointer.
- */
- [[gnu::section(".stl_text")]]
- shared_pointer & operator=(shared_pointer && other) noexcept
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- ref_count = other.ref_count;
- other.pointer = nullptr;
- other.ref_count = nullptr;
- }
-
- return *this;
- }
-
- /**
- * @brief Destructor. Cleans up resources if necessary.
- */
- [[gnu::section(".stl_text")]]
- ~shared_pointer()
- {
- cleanup();
- }
-
- /**
- * @brief Replaces the managed object.
- *
- * @param ptr Pointer to a new object to manage (default = nullptr).
- */
- [[gnu::section(".stl_text")]]
- void reset(T * ptr = nullptr)
- {
- cleanup();
- pointer = ptr;
- ref_count = new std::atomic<std::size_t>(ptr != nullptr ? 1 : 0);
- }
-
- /**
- * @brief Exchanges the stored pointer values and the ownerships of *this and r. Reference counts, if any, are not
- * adjusted.
- *
- * @param other The shared_pointer to swap with.
- */
- [[gnu::section(".stl_text")]]
- void swap(shared_pointer & other)
- {
- std::swap(pointer, other.pointer);
- std::swap(ref_count, other.ref_count);
- }
-
- /**
- * @brief Dereference operator. If get() is a null pointer, the behavior is undefined.
- *
- * @return Returns the object owned by *this, equivalent to *get().
- */
- [[gnu::section(".stl_text")]]
- auto operator*() const -> T &
- {
- return *pointer;
- }
-
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
- [[gnu::section(".stl_text")]]
- auto operator->() const -> T *
- {
- return pointer;
- }
-
- /**
- * @brief Returns a pointer to the managed object or nullptr if no object is owned.
- *
- * @return Pointer to the managed object or nullptr if no object is owned.
- */
- [[gnu::section(".stl_text")]]
- auto get() const -> T *
- {
- return pointer;
- }
-
- /**
- * @brief Returns the number of different shared_pointer instances (*this included) managing the current object. If
- * there is no managed object, ​0​ is returned.
- *
- * @note Common use cases include comparison with ​0​. If use_count returns zero, the shared pointer is empty
- * and manages no objects (whether or not its stored pointer is nullptr). Comparison with 1. If use_count returns 1,
- * there are no other owners.
- *
- * @return The number of Shared_pointer instances managing the current object or ​0​ if there is no managed
- * object.
- */
- [[gnu::section(".stl_text")]]
- auto use_count() const -> std::size_t
- {
- if (pointer != nullptr)
- {
- return *ref_count;
- }
-
- return 0;
- }
-
- /**
- * @brief Checks whether *this owns an object, i.e. whether get() != nullptr.
- *
- * @return true if *this owns an object, false otherwise.
- */
- [[gnu::section(".stl_text")]]
- explicit operator bool() const
- {
- return pointer != nullptr;
- }
-
- /**
- * @brief Defaulted three-way comparator operator.
- */
- [[gnu::section(".stl_text")]]
- auto operator<=>(const shared_pointer & other) const = default;
-
- private:
- /**
- * @brief Releases ownership and deletes the object if this was the last ereference to the owned managed object.
- */
- [[gnu::section(".stl_text")]]
- auto cleanup() -> void
- {
- if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0)
- {
- delete pointer;
- delete ref_count;
- }
- }
-
- T * pointer; ///< The managed object.
- std::atomic<std::size_t> * ref_count; ///< Reference count.
- };
-
- /**
- * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls
- * lhs.swap(rhs).
- *
- * @tparam T Type of the managed object.
- * @param lhs, rhs Smart pointers whose contents to swap.
- */
- template<typename T>
- auto swap(shared_pointer<T> & lhs, shared_pointer<T> & rhs) -> void
- {
- lhs.swap(rhs);
- }
-
- /**
- * @brief Constructs an object of type T and wraps it in a shared_pointer. Constructs a non-array type T. The
- * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is
- * not an array type. The function is equivalent to: shared_pointer<T>(new T(std::forward<Args>(args)...)).
- *
- * @tparam T Type of the managed object.
- * @tparam Args Argument types for T's constructor.
- * @param args List of arguments with which an instance of T will be constructed.
- * @returns Shared_pointer of an instance of type T.
- */
- template<typename T, typename... Args>
- auto make_shared(Args &&... args) -> shared_pointer<T>
- {
- return shared_pointer<T>(new T(std::forward<Args>(args)...));
- }
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp
deleted file mode 100644
index 48bcf10..0000000
--- a/arch/x86_64/include/arch/stl/stack.hpp
+++ /dev/null
@@ -1,212 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_STACK_HPP
-#define TEACHOS_ARCH_X86_64_STL_STACK_HPP
-
-#include "arch/exception_handling/panic.hpp"
-#include "arch/stl/vector.hpp"
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Custom stack implementation mirroring the std::stack to allow for the usage of STL functionality with our
- * custom memory management.
- *
- * @tparam T Element the stack instance should contain.
- * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires
- * access to pop_back(), push_back(), back(), size(), empty() and emplace_back()
- */
- template<typename T, typename Container = stl::vector<T>>
- struct stack
- {
- using container_type = Container; ///< Type of the underlying container used to implement stack-like interface.
- using value_type = Container::value_type; ///< Type of the elements contained in the underlying container.
- using size_type = Container::size_type; ///< Type of the size in the underlying container.
- using reference = Container::reference; ///< Type of reference to the elements.
- using const_reference = Container::const_reference; ///< Type of constant reference to the elements.
-
- /**
- * @brief Default Constructor.
- */
- stack() = default;
-
- /**
- * @brief Constructs data with the given amount of elements containg the given value or alterantively the default
- * constructed value.
- *
- * @param n Amount of elements we want to create and set the given value for.
- * @param initial Inital value of all elements in the underlying data array.
- */
- [[gnu::section(".stl_text")]]
- explicit stack(size_type n, value_type initial = value_type{})
- : _container(n, initial)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Constructs data by copying all element from the given exclusive range.
- *
- * @tparam InputIterator Template that should have atleast input iterator characteristics.
- * @param first Input iterator to the first element in the range we want to copy from.
- * @param last Input iterator to one past the last element in the range we want to copy from.
- */
- template<typename InputIterator>
- [[gnu::section(".stl_text")]]
- explicit stack(InputIterator first, InputIterator last)
- : _container(first, last)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Construct data by copying all elements from the initializer list.
- *
- * @param initalizer_list List we want to copy all elements from.
- */
- [[gnu::section(".stl_text")]]
- explicit stack(std::initializer_list<T> initalizer_list)
- : _container(initalizer_list)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Copy constructor.
- *
- * @note Allocates underlying data container with the same capacity as stack we are copying from and copies all
- * elements from it.
- *
- * @param other Other instance of stack we want to copy the data from.
- */
- [[gnu::section(".stl_text")]]
- stack(stack<T> const & other)
- : _container(other)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Copy assignment operator.
- *
- * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all
- * elements from it.
- *
- * @param other Other instance of vector we want to copy the data from.
- * @return Newly created copy.
- */
- [[gnu::section(".stl_text")]]
- stack<T> & operator=(stack<T> const & other)
- {
- _container = other;
- }
-
- /**
- * @brief Destructor.
- */
- ~stack() = default;
-
- /**
- * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If
- * that is the case the capacity is increased automatically.
- *
- * @return Current amount of elements.
- */
- [[gnu::section(".stl_text")]]
- auto size() const -> size_type
- {
- return _container.size();
- }
-
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
- [[gnu::section(".stl_text")]]
- auto top() -> reference
- {
- return _container.back();
- }
-
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
- [[gnu::section(".stl_text")]]
- auto top() const -> const_reference
- {
- return _container.back();
- }
-
- /**
- * @brief Appends the given element value to the end of the container. The element is assigned through the
- * assignment operator of the template type. The value is forwarded to the constructor as
- * std::forward<U>(value), meaning it is either moved (rvalue) or copied (lvalue).
- *
- * @note If after the operation the new size() is greater than old capacity() a reallocation takes place,
- * in which case all iterators (including the end() iterator) and all references to the elements are invalidated.
- * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @param value The value of the element to append.
- */
- template<class U>
- [[gnu::section(".stl_text")]]
- auto push(U && value) -> void
- {
- _container.push_back(std::forward<U>(value));
- }
-
- /**
- * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the
- * template type. The arguments args... are forwarded to the constructor as std::forward<Args>(args)....
- *
- * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case
- * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only
- * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @tparam Args
- * @param args Arguments to forward to the constructor of the element
- * @return value_type&
- */
- template<class... Args>
- [[gnu::section(".stl_text")]]
- auto emplace(Args &&... args) -> reference
- {
- _container.emplace_back(std::forward<Args>(args)...);
- }
-
- /**
- * @brief Removes the last element of the container.
- *
- * @note Calling pop_back on an empty container results in halting the
- * further execution. Iterators and references to the last element are invalidated. The end()
- * iterator is also invalidated.
- */
- [[gnu::section(".stl_text")]]
- auto pop() -> void
- {
- _container.pop_back();
- }
-
- /**
- * @brief Wheter there are currently any items this container or not.
- *
- * @return True if there are no elements, false if there are.
- */
- [[gnu::section(".stl_text")]]
- auto empty() const -> bool
- {
- return _container.empty();
- }
-
- private:
- container_type _container = {}; ///< Underlying container used by the stack to actually save the data.
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_STACK_HPP
diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp
deleted file mode 100644
index 03b4ef3..0000000
--- a/arch/x86_64/include/arch/stl/unique_pointer.hpp
+++ /dev/null
@@ -1,204 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP
-#define TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Unique_pointer is a smart pointer that owns (is responsible for) and manages another object via a pointer
- * and subsequently disposes of that object when the unique_pointer goes out of scope.
- *
- * @tparam T Type of the managed object.
- */
- template<typename T>
- struct unique_pointer
- {
- /**
- * @brief Constructor.
- *
- * @param ptr A pointer to an object to manage (default is nullptr).
- */
- [[gnu::section(".stl_text")]]
- explicit unique_pointer(T * ptr = nullptr)
- : pointer(ptr)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Destructor that deletes the managed object.
- */
- [[gnu::section(".stl_text")]]
- ~unique_pointer()
- {
- delete pointer;
- }
-
- /**
- * @brief Deleted copy constructor to enforce unique ownership.
- */
- unique_pointer(const unique_pointer &) = delete;
-
- /**
- * @brief Deleted copy assignment operator to enforce unique ownership.
- */
- auto operator=(const unique_pointer &) -> unique_pointer & = delete;
-
- /**
- * @brief Move constructor.
- *
- * @param other Unique pointer to move from.
- */
- [[gnu::section(".stl_text")]]
- unique_pointer(unique_pointer && other) noexcept
- : pointer(other.pointer)
- {
- other.pointer = nullptr;
- }
-
- /**
- * @brief Move assignment operator. Transfers ownership from other to *this as if by calling reset(r.release()).
- *
- * @param other Smart pointer from which ownership will be transferred.
- * @return Reference to this unique pointer.
- */
- [[gnu::section(".stl_text")]]
- auto operator=(unique_pointer && other) noexcept -> unique_pointer &
- {
- if (this != &other)
- {
- delete pointer;
- pointer = other.pointer;
- other.pointer = nullptr;
- }
- return *this;
- }
-
- /**
- * @brief Dereference operator. If get() is a null pointer, the behavior is undefined.
- *
- * @return Returns the object owned by *this, equivalent to *get().
- */
- [[gnu::section(".stl_text")]]
- auto operator*() const -> T &
- {
- return *pointer;
- }
-
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
- [[gnu::section(".stl_text")]]
- auto operator->() const -> T *
- {
- return pointer;
- }
-
- /**
- * @brief Returns a pointer to the managed object or nullptr if no object is owned.
- *
- * @return Pointer to the managed object or nullptr if no object is owned.
- */
- [[gnu::section(".stl_text")]]
- auto get() const -> T *
- {
- return pointer;
- }
-
- /**
- * @brief Checks whether *this owns an object, i.e. whether get() != nullptr.
- *
- * @return true if *this owns an object, false otherwise.
- */
- [[gnu::section(".stl_text")]]
- explicit operator bool() const noexcept
- {
- return pointer != nullptr;
- }
-
- /**
- * @brief Releases the ownership of the managed object, if any.
- * get() returns nullptr after the call.
- * The caller is responsible for cleaning up the object (e.g. by use of get_deleter()).
- *
- * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be
- * returned by get() before the call.
- */
- [[gnu::section(".stl_text")]]
- auto release() -> T *
- {
- T * temp = pointer;
- pointer = nullptr;
- return temp;
- }
-
- /**
- * @brief Replaces the managed object.
- *
- * @note A test for self-reset, i.e. whether ptr points to an object already managed by *this, is not performed,
- * except where provided as a compiler extension or as a debugging assert. Note that code such as
- * p.reset(p.release()) does not involve self-reset, only code like p.reset(p.get()) does.
- *
- * @param ptr Pointer to a new object to manage (default = nullptr).
- */
- [[gnu::section(".stl_text")]]
- auto reset(T * ptr = nullptr) -> void
- {
- delete pointer;
- pointer = ptr;
- }
-
- /**
- * @brief Swaps the managed objects and associated deleters of *this and another unique_ptr object other.
- *
- * @param other Another unique_ptr object to swap the managed object and the deleter with.
- */
- [[gnu::section(".stl_text")]]
- auto swap(unique_pointer & other) -> void
- {
- using std::swap;
- swap(pointer, other.pointer);
- }
-
- /**
- * @brief Defaulted three-way comparator operator.
- */
- [[gnu::section(".stl_text")]]
- auto operator<=>(const unique_pointer & other) const = default;
-
- private:
- T * pointer; ///< The managed pointer.
- };
-
- /**
- * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls
- * lhs.swap(rhs).
- *
- * @tparam T Type of the managed object.
- * @param lhs, rhs Smart pointers whose contents to swap.
- */
- template<typename T>
- auto swap(unique_pointer<T> & lhs, unique_pointer<T> & rhs) -> void
- {
- lhs.swap(rhs);
- }
-
- /**
- * @brief Constructs an object of type T and wraps it in a unique_pointer. Constructs a non-array type T. The
- * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is
- * not an array type. The function is equivalent to: unique_pointer<T>(new T(std::forward<Args>(args)...)).
- *
- * @tparam T Type of the managed object.
- * @tparam Args Argument types for T's constructor.
- * @param args List of arguments with which an instance of T will be constructed.
- * @returns Unique_pointer of an instance of type T.
- */
- template<typename T, typename... Args>
- auto make_unique(Args &&... args) -> unique_pointer<T>
- {
- return unique_pointer<T>(new T(std::forward<Args>(args)...));
- }
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp
deleted file mode 100644
index 5314029..0000000
--- a/arch/x86_64/include/arch/stl/vector.hpp
+++ /dev/null
@@ -1,601 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
-#define TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
-
-#include "arch/exception_handling/panic.hpp"
-#include "arch/stl/container.hpp"
-#include "arch/stl/contiguous_pointer_iterator.hpp"
-
-#include <algorithm>
-
-namespace teachos::arch::stl
-{
- /**
- * @brief Custom vector implementation mirroring the std::vector to allow for the usage of STL functionality with our
- * custom memory management.
- *
- * @tparam T Element the vector instance should contain.
- */
- template<typename T>
- struct vector
- {
- using value_type = T; ///< Type of the elements contained in the container.
- using size_type = std::size_t; ///< Type of the size in the container.
- using reference = value_type &; ///< Type of reference to the elements.
- using const_reference = value_type const &; ///< Type of constant reference to the elements.
- using pointer = value_type *; ///< Type of pointer to the elements.
- using const_pointer = value_type const *; ///< Type of constant pointer to the elements.
-
- /**
- * @brief Default Constructor.
- */
- vector() = default;
-
- /**
- * @brief Constructs data with the given amount of elements containg the given value or alterantively the default
- * constructed value.
- *
- * @param n Amount of elements we want to create and set the given value for.
- * @param initial Inital value of all elements in the underlying data array.
- */
- explicit vector(size_type n, value_type initial = value_type{})
- : _size(n)
- , _capacity(n)
- , _data(new value_type[_capacity]{})
- {
- std::ranges::fill(*this, initial);
- }
-
- /**
- * @brief Constructs data by copying all element from the given exclusive range.
- *
- * @tparam InputIterator Template that should have atleast input iterator characteristics.
- * @param first Input iterator to the first element in the range we want to copy from.
- * @param last Input iterator to one past the last element in the range we want to copy from.
- */
- template<typename InputIterator>
- explicit vector(InputIterator first, InputIterator last)
- : _size(std::distance(first, last))
- , _capacity(std::distance(first, last))
- , _data(new value_type[_capacity]{})
- {
- stl::container<InputIterator> container{first, last};
- std::ranges::copy(container, _data);
- }
-
- /**
- * @brief Construct data by copying all elements from the initializer list.
- *
- * @param initalizer_list List we want to copy all elements from.
- */
- explicit vector(std::initializer_list<value_type> initalizer_list)
- : _size(initalizer_list.size())
- , _capacity(initalizer_list.size())
- , _data(new value_type[_capacity]{})
- {
- std::ranges::copy(initalizer_list, _data);
- }
-
- /**
- * @brief Copy constructor.
- *
- * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all
- * elements from it.
- *
- * @param other Other instance of vector we want to copy the data from.
- */
- vector(vector<value_type> const & other)
- : _size(other._size)
- , _capacity(other._capacity)
- {
- delete[] _data;
- _data = new value_type[_capacity]{};
- std::ranges::copy(other, _data);
- }
-
- /**
- * @brief Copy assignment operator.
- *
- * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all
- * elements from it.
- *
- * @param other Other instance of vector we want to copy the data from.
- * @return Newly created copy.
- */
- [[gnu::section(".stl_text")]]
- vector<value_type> & operator=(vector<value_type> const & other)
- {
- delete[] _data;
- _size = other._size;
- _capacity = other._capacity;
- _data = new value_type[_capacity]{};
- std::ranges::copy(other, _data);
- return *this;
- }
-
- /**
- * @brief Destructor.
- */
- ~vector() { delete[] _data; }
-
- /**
- * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If
- * that is the case the capacity is increased automatically.
- *
- * @return Current amount of elements.
- */
- [[gnu::section(".stl_text")]]
- auto size() const -> size_type
- {
- return _size;
- }
-
- /**
- * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we
- * exactly require to decrease the amount of allocations and deallocation to improve speed.
- *
- * @return Current amount of space the vector has for elements.
- */
- [[gnu::section(".stl_text")]]
- auto capacity() const -> size_type
- {
- return _capacity;
- }
-
- /**
- * @brief Array indexing operator. Allowing to access element at the given index.
- *
- * @note Does not do any bounds checks use at() for that.
- *
- * @param index Index we want to access elements at.
- * @return Reference to the underlying element.
- */
- [[gnu::section(".stl_text")]]
- auto operator[](size_type index) -> reference
- {
- return _data[index];
- }
-
- /**
- * @brief Array indexing operator. Allowing to access element at the given index.
- *
- * @note Does not do any bounds checks use at() for that.
- *
- * @param index Index we want to access elements at.
- * @return Reference to the underlying element.
- */
- [[gnu::section(".stl_text")]]
- auto operator[](size_type index) const -> const_reference
- {
- return _data[index];
- }
-
- /**
- * @brief Array indexing operator. Allowing to access element at the given index.
- *
- * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted.
- *
- * @param index Index we want to access elements at.
- * @return Reference to the underlying element.
- */
- [[gnu::section(".stl_text")]]
- auto at(size_type index) -> reference
- {
- throw_if_out_of_range(index);
- return this->operator[](index);
- }
-
- /**
- * @brief Array indexing operator. Allowing to access element at the given index.
- *
- * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted.
- *
- * @param index Index we want to access elements at.
- * @return Reference to the underlying element.
- */
- [[gnu::section(".stl_text")]]
- auto at(size_type index) const -> const_reference
- {
- throw_if_out_of_range(index);
- return this->operator[](index);
- }
-
- /**
- * @brief Appends the given element value to the end of the container. The element is assigned through the
- * assignment operator of the template type. The value is forwarded to the constructor as
- * std::forward<U>(value), meaning it is either moved (rvalue) or copied (lvalue).
- *
- * @note If after the operation the new size() is greater than old capacity() a reallocation takes place,
- * in which case all iterators (including the end() iterator) and all references to the elements are invalidated.
- * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @param value The value of the element to append.
- */
- template<class U>
- [[gnu::section(".stl_text")]]
- auto push_back(U && value) -> void
- {
- increase_capacity_if_full();
- _data[_size] = std::forward<U>(value);
- (void)_size++;
- }
-
- /**
- * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the
- * template type. The arguments args... are forwarded to the constructor as std::forward<Args>(args)....
- *
- * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case
- * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only
- * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which
- * allows the template method to be used by both lvalue and rvalues and compile a different implementation.
- *
- * @tparam Args
- * @param args Arguments to forward to the constructor of the element
- * @return value_type&
- */
- template<class... Args>
- [[gnu::section(".stl_text")]]
- auto emplace_back(Args &&... args) -> value_type &
- {
- increase_capacity_if_full();
- _data[_size] = value_type{std::forward<Args>(args)...};
- auto const index = _size++;
- return _data[index];
- }
-
- /**
- * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the
- * further execution. Iterators and references to the last element are invalidated. The end()
- * iterator is also invalidated.
- */
- [[gnu::section(".stl_text")]]
- auto pop_back() -> void
- {
- throw_if_empty();
- (void)_size--;
- }
-
- /**
- * @brief Returns an iterator to the first element of the vector.
- * If the vector is empty, the returned iterator will be equal to end().
- *
- * @return Iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto begin() noexcept -> pointer
- {
- return _data;
- }
-
- /**
- * @brief Returns an iterator to the first element of the vector.
- * If the vector is empty, the returned iterator will be equal to end().
- *
- * @return Iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto begin() const noexcept -> const_pointer
- {
- return _data;
- }
-
- /**
- * @brief Returns an iterator to the first element of the vector.
- * If the vector is empty, the returned iterator will be equal to end().
- *
- * @return Iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto cbegin() const noexcept -> const_pointer
- {
- return begin();
- }
-
- /**
- * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element
- * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend().
- *
- * @return Reverse iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto rbegin() noexcept -> pointer
- {
- return _data + _size - 1;
- }
-
- /**
- * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element
- * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend().
- *
- * @return Reverse iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto rbegin() const noexcept -> const_pointer
- {
- return _data + _size - 1;
- }
-
- /**
- * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element
- * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend().
- *
- * @return Reverse iterator to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto crbegin() const noexcept -> const_pointer
- {
- return rbegin();
- }
-
- /**
- * @brief Returns an iterator to the element following the last element of the vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto end() noexcept -> pointer
- {
- return _data + _size;
- }
-
- /**
- * @brief Returns an iterator to the element following the last element of the vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto end() const noexcept -> const_pointer
- {
- return _data + _size;
- }
-
- /**
- * @brief Returns an iterator to the element following the last element of the vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto cend() const noexcept -> const_pointer
- {
- return end();
- }
-
- /**
- * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It
- * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Reverse iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto rend() noexcept -> pointer
- {
- return _data + size - 1;
- }
-
- /**
- * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It
- * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Reverse iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto rend() const noexcept -> const_pointer
- {
- return _data + size - 1;
- }
-
- /**
- * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It
- * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a
- * placeholder, attempting to access it results in undefined behavior.
- *
- * @return Reverse iterator to the element following the last element.
- */
- [[gnu::section(".stl_text")]]
- auto crend() const noexcept -> const_pointer
- {
- return rbegin();
- }
-
- /**
- * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range
- * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable
- * in that case).
- *
- * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal
- * to the address of the first element.
- */
- [[gnu::section(".stl_text")]]
- auto data() -> pointer
- {
- return _data;
- }
-
- /**
- * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range
- * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable
- * in that case).
- *
- * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal
- * to the address of the first element.
- */
- [[gnu::section(".stl_text")]]
- auto data() const -> const_pointer
- {
- return _data;
- }
-
- /**
- * @brief Returns a reference to the first element in the container. Calling front on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto front() -> reference
- {
- throw_if_empty();
- return *begin();
- }
-
- /**
- * @brief Returns a reference to the first element in the container. Calling front on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the first element.
- */
- [[gnu::section(".stl_text")]]
- auto front() const -> const_reference
- {
- throw_if_empty();
- return *begin();
- }
-
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
- [[gnu::section(".stl_text")]]
- auto back() -> reference
- {
- throw_if_empty();
- return *rbegin();
- }
-
- /**
- * @brief Returns a reference to the last element in the container. Calling back on an empty container causes
- * undefined behavior.
- *
- * @return Reference to the last element.
- */
- [[gnu::section(".stl_text")]]
- auto back() const -> const_reference
- {
- throw_if_empty();
- return *rbegin();
- }
-
- /**
- * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without
- * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current
- * capacity(), new storage is allocated, otherwise the function does nothing.
- *
- * reserve() does not change the size of the vector.
- *
- * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the
- * elements are invalidated. Otherwise, no iterators or references are invalidated.
- *
- * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of
- * the vector greater than the value of capacity().
- *
- * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for
- * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing
- * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and
- * decreased performance. For example, a function that receives an arbitrary vector by reference and appends
- * elements to it should usually not call reserve() on the vector, since it does not know of the vector's usage
- * characteristics.
- *
- * When inserting a range, the range version of insert() is generally preferable as it preserves the correct
- * capacity growth behavior, unlike reserve() followed by a series of push_back()s.
- *
- * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided.
- *
- * @param new_capacity New capacity of the vector, in number of elements
- */
- [[gnu::section(".stl_text")]]
- auto reserve(size_type new_capacity) -> void
- {
- if (new_capacity <= _capacity)
- {
- return;
- }
-
- _capacity = new_capacity;
- value_type * temp = new value_type[_capacity]{};
- stl::container<value_type *> container{begin(), end()};
- std::ranges::copy(container, temp);
- delete[] _data;
- _data = temp;
- }
-
- /**
- * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size().
- *
- * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are
- * invalidated. If no reallocation occurs, no iterators or references are invalidated.
- */
- [[gnu::section(".stl_text")]]
- auto shrink_to_fit() -> void
- {
- if (_size == _capacity)
- {
- return;
- }
-
- _capacity = _size;
- value_type * temp = new value_type[_capacity]{};
- stl::container<value_type *> container{begin(), end()};
- std::copy(container, temp);
- delete[] _data;
- _data = temp;
- }
-
- /**
- * @brief Wheter there are currently any items this container or not.
- *
- * @return True if there are no elements, false if there are.
- */
- [[gnu::section(".stl_text")]]
- auto empty() const -> bool
- {
- return _size <= 0;
- }
-
- private:
- /**
- * @brief Halts the execution of the application if the data container is currently empty.
- */
- auto throw_if_empty() const -> void
- {
- if (empty())
- {
- exception_handling::panic("[Vector] Attempted to access element of currently empty vector");
- }
- }
-
- auto throw_if_out_of_range(size_type index) const -> void
- {
- if (index >= _size)
- {
- exception_handling::panic("[Vector] Attempted to read element at invalid index");
- }
- }
-
- /**
- * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential
- * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is
- * normally perferable for the cache.
- */
- auto increase_capacity_if_full() -> void
- {
- if (_size == _capacity)
- {
- reserve(_capacity == 0U ? 1U : _capacity * 2U);
- }
- }
-
- size_type _size = {}; ///< Amount of elements in the underlying data container
- size_type _capacity = {}; ///< Amount of space for elements in the underlying data container
- value_type * _data = {}; ///< Pointer to the first element in the underlying data container
- };
-
-} // namespace teachos::arch::stl
-
-#endif // TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp
deleted file mode 100644
index c168a1f..0000000
--- a/arch/x86_64/include/arch/user/main.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#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
diff --git a/arch/x86_64/include/arch/video/vga/io.hpp b/arch/x86_64/include/arch/video/vga/io.hpp
deleted file mode 100644
index c399fad..0000000
--- a/arch/x86_64/include/arch/video/vga/io.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_VIDEO_VGA_IO_HPP
-#define TEACHOS_ARCH_X86_64_VIDEO_VGA_IO_HPP
-
-#include "arch/io/port_io.hpp"
-
-#include <cstddef>
-
-namespace teachos::arch::video::vga
-{
- namespace crtc
- {
- /**
- * @brief The address port of the CRT Controller.
- */
- using address_port = arch::io::port<0x3d4, 1>;
-
- /**
- * @brief The data port of the CRT Controller.
- */
- using data_port = arch::io::port<0x3d5, 1>;
-
- namespace registers
- {
- /**
- * @brief The address of the Cursor Start register of the CRTC.
- */
- [[maybe_unused]] auto constexpr cursor_start = std::byte{0x0a};
-
- /**
- * @brief The address of the Cursor End register of the CRTC.
- */
- [[maybe_unused]] auto constexpr curser_end = std::byte{0x0b};
- } // namespace registers
-
- }; // namespace crtc
-
-} // namespace teachos::arch::video::vga
-
-#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_IO_HPP
diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp
deleted file mode 100644
index cfbf98f..0000000
--- a/arch/x86_64/include/arch/video/vga/text.hpp
+++ /dev/null
@@ -1,169 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP
-#define TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP
-
-#include <cstdint>
-#include <string_view>
-#include <type_traits>
-
-namespace teachos::arch::video::vga::text
-{
- auto constexpr DEFAULT_VGA_TEXT_BUFFER_ADDRESS = 0xB8000;
-
- /**
- * @brief The colors available in the standard VGA text mode.
- */
- enum struct color : std::uint8_t
- {
- black, ///< Equivalent to HTML color \#000000.
- blue, ///< Equivalent to HTML color \#0000AA.
- green, ///< Equivalent to HTML color \#00AA00.
- cyan, ///< Equivalent to HTML color \#00AAAA.
- red, ///< Equivalent to HTML color \#AA0000.
- purple, ///< Equivalent to HTML color \#AA00AA.
- brown, ///< Equivalent to HTML color \#AA5500.
- gray, ///< Equivalent to HTML color \#AAAAAA.
- };
-
- /**
- * @brief The foreground color modification flag.
- */
- enum struct foreground_flag : bool
- {
- none, ///< Apply no flag e.g., keep color as is.
- intense, ///< Make the color more intense (usually brighter).
- };
-
- /**
- * @brief The background color modification flag.
- */
- enum struct background_flag : bool
- {
- none, ///< Apply no flag e.g., keep color as is.
- blink_or_bright, ///< Make the cell blink or more intense, dependent on the VGA configuration.
- };
-
- /**
- * @brief The VGA text mode attribute.
- *
- * @note In the text mode of VGA, every code point being presented is followed by an attribute description. This
- * allows for the modification of how the relevant "cell" is presented.
- *
- * @see vga::text::foreground_flag
- * @see vga::text::background_flag
- */
- struct attribute
- {
- color foreground_color : 3; ///< The foreground color of the cell, e.g. the color of the code point.
- enum foreground_flag foreground_flag : 1; ///< The foreground color modification flag of the cell.
- color bacground_color : 3; ///< The background color of the cell.
- enum background_flag background_flag : 1; ///< The background color modification flag of the cell.
- };
-
- static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte.");
-
- /**
- * @brief Commonly used VGA text mode attributes.
- */
- namespace common_attributes
- {
- /**
- * @brief Make the affected cell display with a gray foreground and black background.
- */
- [[maybe_unused]] auto constexpr gray_on_black =
- attribute{color::gray, foreground_flag::none, color::black, background_flag::none};
-
- /**
- * @brief Make the affected cell display with a green foreground and black background.
- */
- [[maybe_unused]] auto constexpr green_on_black =
- attribute{color::green, foreground_flag::none, color::black, background_flag::none};
-
- /**
- * @brief Make the affected cell display with a white (gray + intense) foreground and red background.
- */
- [[maybe_unused]] auto constexpr white_on_red =
- attribute{color::gray, foreground_flag::intense, color::red, background_flag::none};
- } // namespace common_attributes
-
- /**
- * @brief Clear the VGA text mode buffer.
- *
- * @note This function also resets the text mode buffer pointer.
- *
- * @param attribute The attribute to "clear" the screen with.
- */
- auto clear(attribute attribute = common_attributes::gray_on_black) -> void;
-
- /**
- * @brief Enable or disable the VGA text mode cursor.
- *
- * @param enabled Whether or not to enable the cursors.
- */
- auto cursor(bool enabled) -> void;
-
- /**
- * @brief Move the cursor to a new line, scrolling the buffer if necessary.
- */
- auto newline() -> void;
-
- /**
- * @brief Write a string of code points to the VGA text buffer.
- *
- * @note This function also updates the text mode buffer pointer.
- *
- * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer.
- * @param attribute The attribute to apply to the written sequence of code points.
- * @see vga::text::attribute
- */
- auto write(std::string_view code_points, attribute attribute) -> void;
-
- /**
- * @brief Write a single character to the VGA text buffer.
- *
- * @note This function also updates the text mode buffer pointer.
- *
- * @param code_point A code point to write to the VGA text mode buffer.
- * @param attribute The attribute to apply to the written sequence of code points.
- * @see vga::text::attribute
- */
- auto write_char(char code_point, attribute attribute) -> void;
-
- template<typename T>
- concept Integral = std::is_integral_v<T>;
-
- /**
- * @brief Write a integral value to the VGA text buffer.
- *
- * @note This function also updates the text mode buffer pointer.
- *
- * @param value A integral value to write to the VGA text mode buffer.
- * @param attribute The attribute to apply to the written sequence of code points.
- * @see vga::text::attribute
- */
- template<Integral T>
- auto write_number(T value, attribute attribute) -> void
- {
- T current_value = value;
- T divisor = 1;
-
- while (current_value > 9)
- {
- divisor *= 10;
- current_value = current_value / 10;
- }
-
- current_value = value;
- while (divisor > 0)
- {
- uint8_t quotient = current_value / divisor;
- char ascii_digit = quotient + '0';
-
- write_char(ascii_digit, attribute);
- current_value %= divisor;
- divisor /= 10;
- }
- }
-
-} // namespace teachos::arch::video::vga::text
-
-#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/boot/boot.hpp b/arch/x86_64/include/x86_64/boot/boot.hpp
new file mode 100644
index 0000000..2c44659
--- /dev/null
+++ b/arch/x86_64/include/x86_64/boot/boot.hpp
@@ -0,0 +1,70 @@
+#ifndef TEACHOS_X86_64_BOOT_BOOT_H
+#define TEACHOS_X86_64_BOOT_BOOT_H
+
+#ifdef __ASSEMBLER__
+/* clang-format off */
+/**
+ * @brief The number of huge pages to map during bootstrap.
+ */
+#define HUGE_PAGES_TO_MAP (16)
+
+/**
+ * @brief The magic value to be set in eax by the multiboot 2 loader.
+ */
+#define MULTIBOOT2_MAGIC (0x36d76289)
+
+/**
+ * @brief The "A" bit in a GDT entry.
+ */
+#define GDT_ACCESSED (1 << 40)
+
+/**
+ * @brief The "R/W" bit in a GDT entry
+ */
+#define GDT_READ_WRITE (1 << 41)
+
+/**
+ * @brief The "E" bit in a GDT entry.
+ */
+#define GDT_EXECUTABLE (1 << 43)
+
+/**
+ * @brief The "S" bit in a GDT entry.
+ */
+#define GDT_DESCRIPTOR_TYPE (1 << 44)
+
+/**
+ * @brief The "P" bit in a GDT entry.
+ */
+#define GDT_PRESENT (1 << 47)
+
+/**
+ * @brief The "L" bit in a GDT entry.
+ */
+#define GDT_LONG_MODE (1 << 53)
+/* clang-format on */
+#else
+
+#include "kapi/boot.hpp" // IWYU pragma: export
+
+#include <multiboot2/information.hpp>
+
+#include <cstddef>
+
+namespace teachos::boot
+{
+
+ struct information
+ {
+ //! A pointer to the loader provided Multiboot2 Information structure.
+ multiboot2::information_view const * mbi;
+
+ //! The index of the next character to be written in the VGA text buffer after handoff.
+ std::size_t vga_buffer_index;
+ };
+
+} // namespace teachos::boot
+
+#endif
+
+#endif
diff --git a/arch/x86_64/include/x86_64/boot/ld.hpp b/arch/x86_64/include/x86_64/boot/ld.hpp
new file mode 100644
index 0000000..b073863
--- /dev/null
+++ b/arch/x86_64/include/x86_64/boot/ld.hpp
@@ -0,0 +1,61 @@
+//! @file
+//! The interface to linker script defined symbols.
+//!
+//! This header provides declarations for symbols that are defined in the linker script itself. The symbols declared
+//! here provide important information, for example the start and end of the kernel image in virtual and physical
+//! memory.
+//!
+//! Any variables defined in this file must not be read themselves, but rather their address shall be taken, yielding a
+//! pointer to the memory location the represent.
+//!
+//! @note The symbols declared in this header are declared using C-language linkage in order to suppress name mangling.
+//!
+//! @see arch/x86_64/scripts/kernel.ld
+
+#ifndef TEACHOS_X86_64_BOOT_LD_HPP
+#define TEACHOS_X86_64_BOOT_LD_HPP
+
+#include <cstddef>
+
+namespace teachos::boot::x86_64
+{
+
+ extern "C"
+ {
+ //! The beginning of the kernel image in physical memory
+ //!
+ //! This symbol marks the start of the kernel image in physical memory.
+ //!
+ //! @see _end_physical
+ extern std::byte _start_physical;
+
+ //! The first byte after the loaded kernel image.
+ //!
+ //! This symbol marks the end of the kernel image in physical memory.
+ //!
+ //! @see _start_physical
+ extern std::byte _end_physical;
+
+ //! The first byte of the loaded kernel image in the virtual address space.
+ //!
+ //! This symbol and marks the start of the kernel image in virtual memory.
+ //!
+ //! @see _end_virtual
+ extern std::byte _start_virtual;
+
+ //! The first byte after the loaded kernel image in the virtual address space.
+ //!
+ //! This symbol marks the end of the kernel image in virtual memory.
+ //!
+ //! @see _start_virtual
+ extern std::byte _end_virtual;
+
+ //! The first byte of the kernel's virtual address space.
+ //!
+ //! This symbol marks beginning of the kernel virtual address space.
+ extern std::byte TEACHOS_VMA;
+ }
+
+} // namespace teachos::boot::x86_64
+
+#endif
diff --git a/arch/x86_64/include/x86_64/cpu/control_register.hpp b/arch/x86_64/include/x86_64/cpu/control_register.hpp
new file mode 100644
index 0000000..35ffcae
--- /dev/null
+++ b/arch/x86_64/include/x86_64/cpu/control_register.hpp
@@ -0,0 +1,244 @@
+#ifndef TEACHOS_X86_64_CPU_IMPL_CONTROL_REGISTERS_HPP
+#define TEACHOS_X86_64_CPU_IMPL_CONTROL_REGISTERS_HPP
+
+// IWYU pragma: private, include "x86_64/cpu/registers.hpp"
+
+#include "kapi/memory/address.hpp"
+
+#include <kstd/ext/bitfield_enum>
+
+#include <cstdint>
+#include <string_view>
+#include <type_traits>
+
+namespace teachos::cpu::x86_64
+{
+ namespace impl
+ {
+ //! The assembler templates used to access (r/w) CR0;
+ constexpr auto static cr0_asm = std::pair<std::string_view, std::string_view>{"mov %%cr0, %0", "mov %0, %%cr0"};
+
+ //! The assembler templates used to access (r/w) CR2;
+ constexpr auto static cr2_asm = std::pair<std::string_view, std::string_view>{"mov %%cr2, %0", "mov %0, %%cr2"};
+
+ //! The assembler templates used to access (r/w) CR3;
+ constexpr auto static cr3_asm = std::pair<std::string_view, std::string_view>{"mov %%cr3, %0", "mov %0, %%cr3"};
+ } // namespace impl
+
+ //! The flags that can be set on CR0 configuration register.
+ enum struct cr0_flags : uint64_t
+ {
+ //! Enable protected mode.
+ protection_enable = 1uz << 0,
+ //! Enable wait-monitoring of the coprocessor after task switching.
+ monitor_coprocessor = 1uz << 1,
+ //! Emulate floating point coprocessor.
+ emulation = 1uz << 2,
+ //! Marks that a task switch has occurred.
+ task_switched = 1uz << 3,
+ //! Marks Intel 387 DX math coprocessor as available
+ extension_type = 1uz << 4,
+ //! Numeric error handling mode.
+ numeric_error = 1uz << 5,
+ //! Disable writing to read-only marked memory.
+ write_protect = 1uz << 16,
+ //! Enable Ring-3 alignment checks
+ alignment_check = 1uz << 18,
+ //! Disable write through
+ not_write_through = 1uz << 29,
+ //! Disable caching of memory accesses
+ cache_disable = 1uz << 30,
+ //! Enable paging
+ paging = 1uz << 31
+ };
+
+ enum struct cr3_flags : std::uint64_t
+ {
+ page_level_write_through = 1uz << 0,
+ page_level_cache_disable = 1uz << 1,
+ };
+} // namespace teachos::cpu::x86_64
+
+namespace kstd::ext
+{
+ template<>
+ struct is_bitfield_enum<teachos::cpu::x86_64::cr0_flags> : std::true_type
+ {
+ };
+
+ template<>
+ struct is_bitfield_enum<teachos::cpu::x86_64::cr3_flags> : std::true_type
+ {
+ };
+} // namespace kstd::ext
+
+namespace teachos::cpu::x86_64
+{
+ //! A mixin for flag-oriented control registers.
+ //!
+ //! This mixin provides additional functionality for flag-oriented, or partially flag-oriented, control registers. A
+ //! control register is flag-oriented, if it comprises a bitfield and zero or more additional non-bitfield parts.
+ //!
+ //! @tparam Derived The class deriving from this mixin.
+ //! @tparam ValueType The value type of the class deriving from this mixin.
+ template<typename Derived, typename ValueType, typename = void>
+ struct control_register_with_flags
+ {
+ };
+
+ //! @copydoc control_register_with_flags
+ //!
+ //! @note This specialization provides the implementation for the case in which the value type of the control register
+ //! is an enum.
+ template<typename Derived, typename ValueType>
+ struct control_register_with_flags<Derived, ValueType, std::enable_if_t<kstd::ext::bitfield_enum<ValueType>>>
+ {
+ //! The type of the flags used by this control register
+ using flags = ValueType;
+
+ //! Set one or more flags in this control register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Setting flags in a control register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param value One or a combination of flags to be set in the control register.
+ auto static set(ValueType value) -> void
+ {
+ auto current = Derived::read();
+ current |= value;
+ Derived::write(current);
+ }
+
+ //! Clear one or more flags in this control register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Clearing flags in a control register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param value One or a combination of flags to be cleared in the control register.
+ auto static clear(ValueType value) -> void
+ {
+ auto current = Derived::read();
+ current &= ~value;
+ Derived::write(current);
+ }
+ };
+
+ //! A CPU control register.
+ //!
+ //! CPU control registers are used to configure builtin features of the CPU, for example memory protection and FPU
+ //! error reporting. Writing to a control register is inherently dangerous, since a misconfiguration can leave the CPU
+ //! in an invalid/undefined state.
+ template<typename ValueType, auto AssemblerTemplates>
+ struct control_register : control_register_with_flags<control_register<ValueType, AssemblerTemplates>, ValueType>
+ {
+ //! Read the current value of the control register.
+ //!
+ //! @return The currently set value of the control register.
+ [[nodiscard]] auto static read() -> ValueType
+ {
+ auto value = ValueType{};
+ asm volatile((AssemblerTemplates->first) : "=r"(value));
+ return value;
+ }
+
+ //! Write a new value to the control register.
+ //!
+ //! @warning This function should be considered **UNSAFE**. Writing values to a control register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param value The new value to write to the control register.
+ auto static write(ValueType value) -> void
+ {
+ asm volatile((AssemblerTemplates->second) : : "r"(value));
+ }
+ };
+
+ //! The value type of the CR3 control register.
+ //!
+ //! The CR3 control register holds the root configuration of the virtual memory protection mechanism. It contains the
+ //! page aligned physical address of the root page map, as well as the root paging configuration flags.
+ struct cr3_value
+ {
+ //! Contstruct a 0-value CR3 value.
+ constexpr cr3_value() = default;
+
+ //! Construct a CR3 value using the given root page map address and flags.
+ //!
+ //! @param address The physical address of the root page map
+ //! @param flags The root configuration flags of the paging system.
+ constexpr cr3_value(memory::physical_address address, cr3_flags flags = static_cast<cr3_flags>(0))
+ : m_flags{static_cast<std::uint64_t>(flags)}
+ , m_address{static_cast<std::uint64_t>(address.raw())}
+ {}
+
+ //! Extract the physical address of the root page map from this value.
+ //!
+ //! @return The physical address of the root page map.
+ [[nodiscard]] constexpr auto address() const -> memory::physical_address
+ {
+ return memory::physical_address{m_address};
+ }
+
+ //! Encode the page aligned physical address of the root page map into this value.
+ //!
+ //! @param address The page aligned physical address of the root page map.
+ constexpr auto address(memory::physical_address address) -> void
+ {
+ m_address = static_cast<std::uint64_t>(address.raw());
+ }
+
+ //! Extract the root paging configuration flags from this value.
+ //!
+ //! @return The root paging configuration flags.
+ [[nodiscard]] constexpr auto flags() const -> cr3_flags
+ {
+ return static_cast<cr3_flags>(m_flags);
+ }
+
+ //! Encode the root paging configuration flags into this value.
+ //!
+ //! @param flags The root paging configuration flags.
+ constexpr auto flags(cr3_flags flags) -> void
+ {
+ m_flags = static_cast<std::uint64_t>(flags);
+ }
+
+ //! Add the given flags to the current set of encoded root configuration flags of this value.
+ //!
+ //! @param flags The root configuration flags to add.
+ //! @return A reference to this value.
+ constexpr auto operator|=(cr3_flags flags) -> cr3_value &
+ {
+ m_flags |= static_cast<std::uint64_t>(flags);
+ return *this;
+ }
+
+ //! Mask the root configuration flags of this value.
+ //!
+ //! @param mask The mask to apply to the root configuration flags.
+ //! @return A reference to this value.
+ constexpr auto operator&=(cr3_flags mask) -> cr3_value &
+ {
+ m_flags &= static_cast<std::uint64_t>(mask);
+ return *this;
+ }
+
+ private:
+ //! Reserved bits.
+ std::uint64_t : 3;
+ //! The root paging configuration flags.
+ std::uint64_t m_flags : 2 {};
+ //! Reserved bits.
+ std::uint64_t : 7;
+ //! The page aligned physical address of the root page map.
+ std::uint64_t m_address : 52 {};
+ };
+
+ static_assert(sizeof(cr3_value) == sizeof(std::uint64_t));
+
+} // namespace teachos::cpu::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/cpu/model_specific_register.hpp b/arch/x86_64/include/x86_64/cpu/model_specific_register.hpp
new file mode 100644
index 0000000..857b444
--- /dev/null
+++ b/arch/x86_64/include/x86_64/cpu/model_specific_register.hpp
@@ -0,0 +1,148 @@
+#ifndef TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP
+#define TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP
+
+// IWYU pragma: private, include "x86_64/cpu/registers.hpp"
+
+#include <kstd/ext/bitfield_enum>
+
+#include <bit>
+#include <cstdint>
+#include <type_traits>
+
+namespace teachos::cpu::x86_64
+{
+
+ //! The flags of the IA32_EFER (Extended Features Enable Register) MSR.
+ enum struct ia32_efer_flags : std::uint64_t
+ {
+ //! Enable the syscall and sysret instructions.
+ syscall_enable = 1uz << 0,
+ //! Enable IA-32e mode operation.
+ ia32e_mode_enable = 1uz << 8,
+ //! Indicates IA-32e mode is active (read-only)
+ ia32e_mode_active = 1uz << 10,
+ //! Enable the use of the NX page table bit.
+ execute_disable_bit_enable = 1uz << 11,
+ };
+
+} // namespace teachos::cpu::x86_64
+
+namespace kstd::ext
+{
+
+ template<>
+ struct is_bitfield_enum<teachos::cpu::x86_64::ia32_efer_flags> : std::true_type
+ {
+ };
+
+} // namespace kstd::ext
+
+namespace teachos::cpu::x86_64
+{
+ //! The MSR number for the IA32_EFER MSR
+ constexpr auto ia32_efer_number = 0xC000'0080u;
+
+ //! A mixin for flag-oriented model specific registers.
+ //!
+ //! This mixin provides additional functionality for a flag-oriented model specific register. A models specific
+ //! register is flag-oriented, if it comprises a single field of bitfield.
+ //!
+ //! @tparam Derived The class deriving from this mixin.
+ //! @tparam ValueType The value type of the class deriving from this mixin.
+ template<typename Derived, typename ValueType, typename = void>
+ struct model_specific_register_with_flags
+ {
+ };
+
+ //! @copydoc model_specific_register_with_flags
+ //!
+ //! @note This specialization provides the implementation for the case in which the value type of the model specific
+ //! register is a bitfield enum.
+ template<typename Derived, typename ValueType>
+ struct model_specific_register_with_flags<Derived, ValueType, std::enable_if_t<kstd::ext::bitfield_enum<ValueType>>>
+ {
+ //! The of the flags used by this model specific register.
+ using flags = ValueType;
+
+ //! Set one or more flags in this model specific register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Setting flags in a model specific register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param flag One or a combination of flags to be set in the model specific register.
+ auto static set(flags flag) -> void
+ {
+ auto current = Derived::read();
+ current |= flag;
+ Derived::write(current);
+ }
+
+ //! Clear one or more flags in this model specific register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Clearing flags in a model specific register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param flag One or a combination of flags to be cleared in the model specific register.
+ auto static clear(flags flag) -> void
+ {
+ auto current = Derived::read();
+ current &= ~flag;
+ Derived::write(current);
+ }
+
+ //! Test one or more flags in this model specific register
+ //!
+ //! @param flag One or a combination of flags to test for.
+ auto test(flags flag) -> flags
+ {
+ return Derived::read() & flag;
+ }
+ };
+
+ //! A model specific register (MSR)
+ //!
+ //! Model specific register are used to configure CPU features that a not necessarily present on all CPUs generations.
+ //! In the past, some MSRs have been defined to be architectural, meaning all CPUs of a given architecture (x86-64 in
+ //! this case) support them. Writing to a MSR is inherently dangerous, since a misconfiguration cal leave the CPU in
+ //! an invalid/undefined state.
+ //!
+ //! @tparam Number The register number of this MSR
+ //! @tparam ValueType The value type of this MSR
+ template<std::uint32_t Number, typename ValueType>
+ struct model_specific_register
+ : model_specific_register_with_flags<model_specific_register<Number, ValueType>, ValueType>
+ {
+ //! A raw MSR value, comprising two halfs.
+ //!
+ //! MSRs have been 64-bit in size even in the 32-bit intel architecture, and are thus written in two halfs.
+ struct raw_value
+ {
+ std::uint32_t low_half; //!< The lower half of the register value
+ std::uint32_t high_half; //!< The upper half of the register value
+ };
+
+ //! Read the current value of this MSR.
+ //!
+ //! @return The current value of this MSR.
+ auto static read() -> ValueType
+ {
+ auto raw = raw_value{};
+ asm volatile("rdmsr" : "=a"(raw.low_half), "=d"(raw.high_half) : "c"(Number));
+ return static_cast<ValueType>(std::bit_cast<std::uint64_t>(raw));
+ }
+
+ //! Write a new value to this MSR.
+ //!
+ //! @param value The new value for this MSR.
+ auto static write(ValueType value) -> void
+ {
+ auto raw = std::bit_cast<raw_value>(static_cast<std::uint64_t>(value));
+ asm volatile("wrmsr" : : "a"(raw.low_half), "d"(raw.high_half), "c"(Number));
+ }
+ };
+
+} // namespace teachos::cpu::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/cpu/registers.hpp b/arch/x86_64/include/x86_64/cpu/registers.hpp
new file mode 100644
index 0000000..8eb89e3
--- /dev/null
+++ b/arch/x86_64/include/x86_64/cpu/registers.hpp
@@ -0,0 +1,30 @@
+#ifndef TEACHOS_X86_64_CPU_REGISTERS_HPP
+#define TEACHOS_X86_64_CPU_REGISTERS_HPP
+
+#include "x86_64/cpu/control_register.hpp" // IWYU pragma: export
+#include "x86_64/cpu/model_specific_register.hpp" // IWYU pragma: export
+
+namespace teachos::cpu::x86_64
+{
+
+ //! Configuration Register 0.
+ //!
+ //! This configuration register holds various control flags to configure the configure the basic operation of the CPU.
+ using cr0 = control_register<cr0_flags, &impl::cr0_asm>;
+
+ //! Configuration Register 2.
+ //!
+ //! This configuration register holds the memory address the access to which has triggered the most recent page fault.
+ using cr2 = control_register<memory::linear_address, &impl::cr2_asm>;
+
+ //! Configuration Register 3.
+ //!
+ //! This register holds the configuration of the virtual memory protection configuration.
+ using cr3 = control_register<cr3_value, &impl::cr3_asm>;
+
+ //! The I32_EFER (Extended Feature Enable Register) MSR
+ using i32_efer = model_specific_register<ia32_efer_number, ia32_efer_flags>;
+
+} // namespace teachos::cpu::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/device_io/port_io.hpp b/arch/x86_64/include/x86_64/device_io/port_io.hpp
new file mode 100644
index 0000000..c3e5271
--- /dev/null
+++ b/arch/x86_64/include/x86_64/device_io/port_io.hpp
@@ -0,0 +1,101 @@
+#ifndef TEACHOS_X86_64_IO_PORT_IO_HPP
+#define TEACHOS_X86_64_IO_PORT_IO_HPP
+
+#include <array>
+#include <concepts>
+#include <cstddef>
+#include <cstdint>
+#include <string_view>
+#include <type_traits>
+
+namespace teachos::io::x86_64
+{
+
+ //! The requirements imposed on a type usable for port I/O.
+ template<typename ValueType>
+ concept port_io_type = requires {
+ requires sizeof(ValueType) == 1 || sizeof(ValueType) == 2 || sizeof(ValueType) == 4;
+ requires std::default_initializable<ValueType>;
+ std::bit_cast<ValueType>(
+ std::conditional_t<sizeof(ValueType) == 1, std::byte,
+ std::conditional_t<sizeof(ValueType) == 2, std::uint16_t, std::uint32_t>>{});
+ };
+
+ template<typename Derived>
+ struct port_read
+ {
+ //! Read from the I/O port.
+ //!
+ //! @return The data read from the I/O port.
+ auto static read() noexcept
+ {
+ auto data = typename Derived::value_type{};
+ asm volatile((code[Derived::size / 2])
+ : [data] "=m"(data)
+ : [port] "i"(Derived::size)
+ : "dx", (Derived::data_register));
+ return data;
+ }
+
+ private:
+ //! The assembly templates used for reading from an I/O port.
+ constexpr auto static code = std::array{
+ std::string_view{"mov %[port], %%dx\nin %%dx, %%al\nmov %%al, %[data]"},
+ std::string_view{"mov %[port], %%dx\nin %%dx, %%ax\nmov %%ax, %[data]"},
+ std::string_view{"mov %[port], %%dx\nin %%dx, %%eax\nmov %%eax, %[data]"},
+ };
+ };
+
+ template<typename Derived>
+ struct port_write
+ {
+ //! Write data to the I/O port.
+ //!
+ //! @param data The data to write to the I/O port.
+ auto static write(std::same_as<typename Derived::value_type> auto data) noexcept -> void
+ {
+ asm volatile((code[Derived::size / 2])
+ :
+ : [port] "i"(Derived::address), [data] "im"(data)
+ : "dx", (Derived::data_register));
+ }
+
+ private:
+ //! The assembly templates used for writing to an I/O port.
+ constexpr auto static code = std::array{
+ std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%al, %%dx"},
+ std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%ax, %%dx"},
+ std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%eax, %%dx"},
+ };
+ };
+
+ //! An I/O port of a given size at a given address.
+ //!
+ //! Port I/O leverages a separate address space to communicate with devices via the memory bus, allowing for byte
+ //! to double-word sized transfers.
+ //!
+ //! @tparam Address The address (port number) of the I/O port.
+ //! @tparam Size The size (in bytes) of the I/O port.
+ //! @tparam Features The features (readable, writeable)
+ template<std::uint16_t Address, port_io_type ValueType, template<typename> typename... Features>
+ requires(sizeof...(Features) > 0)
+ struct port : Features<port<Address, ValueType, Features...>>...
+ {
+ //! The type of the data of this port.
+ using value_type = ValueType;
+
+ //! The address of this I/O port.
+ constexpr auto static address = Address;
+
+ //! The size of this I/O port.
+ constexpr auto static size = sizeof(value_type);
+
+ //! The register clobbered by the I/O operation.
+ constexpr auto static data_register = size == 1 ? std::string_view{"al"}
+ : size == 2 ? std::string_view{"ax"}
+ : std::string_view{"eax"};
+ };
+
+} // namespace teachos::io::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/buffered_allocator.hpp b/arch/x86_64/include/x86_64/memory/buffered_allocator.hpp
new file mode 100644
index 0000000..90ac878
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/buffered_allocator.hpp
@@ -0,0 +1,68 @@
+#ifndef TEACHOS_X86_64_BUFFERED_ALLOCATOR_HPP
+#define TEACHOS_X86_64_BUFFERED_ALLOCATOR_HPP
+
+#include "kapi/memory.hpp"
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <optional>
+
+namespace teachos::memory::x86_64
+{
+
+ template<std::size_t BufferSize>
+ struct buffered_allocator : frame_allocator
+ {
+ explicit buffered_allocator(frame_allocator * underlying)
+ : m_underlying{underlying}
+ {
+ std::ranges::generate(m_pool, [this] { return m_underlying->allocate(); });
+ }
+
+ buffered_allocator(buffered_allocator const &) = delete;
+ buffered_allocator(buffered_allocator && other) noexcept = delete;
+
+ ~buffered_allocator() override
+ {
+ std::ranges::for_each(m_pool, [this](auto const & maybe_frame) {
+ if (maybe_frame)
+ {
+ m_underlying->release(*maybe_frame);
+ }
+ });
+ }
+
+ auto operator=(buffered_allocator const &) = delete;
+ auto operator=(buffered_allocator &&) = delete;
+
+ auto allocate() noexcept -> std::optional<frame> override
+ {
+ auto found = std::ranges::find_if(m_pool, [](auto const & candidate) { return candidate.has_value(); });
+ if (found == std::end(m_pool))
+ {
+ return m_underlying->allocate();
+ }
+ auto frame = found->value();
+ found->reset();
+ return frame;
+ }
+
+ auto release(frame frame) -> void override
+ {
+ auto found = std::ranges::find_if(m_pool, [](auto const & candidate) { return !candidate; });
+ if (found == std::end(m_pool))
+ {
+ return m_underlying->release(frame);
+ }
+ (*found) = frame;
+ }
+
+ private:
+ frame_allocator * m_underlying;
+ std::array<std::optional<frame>, BufferSize> m_pool{};
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/kernel_mapper.hpp b/arch/x86_64/include/x86_64/memory/kernel_mapper.hpp
new file mode 100644
index 0000000..5b9c2fd
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/kernel_mapper.hpp
@@ -0,0 +1,32 @@
+#ifndef TEACHOS_X86_64_KERNEL_MAPPER_HPP
+#define TEACHOS_X86_64_KERNEL_MAPPER_HPP
+
+#include "kapi/memory.hpp"
+
+#include <elf/format.hpp>
+#include <elf/section_header.hpp>
+#include <multiboot2/information.hpp>
+
+#include <string_view>
+
+namespace teachos::memory::x86_64
+{
+
+ struct kernel_mapper
+ {
+ using section_header_type = elf::section_header<elf::format::elf64>;
+
+ explicit kernel_mapper(multiboot2::information_view const * mbi);
+
+ auto remap_kernel(page_mapper & mapper) -> void;
+
+ private:
+ auto map_section(section_header_type const & section, std::string_view name, page_mapper & mapper) -> void;
+
+ multiboot2::information_view const * m_mbi;
+ std::uintptr_t m_kernel_load_base;
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp b/arch/x86_64/include/x86_64/memory/mmu.hpp
index f3e58a6..323d18a 100644
--- a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp
+++ b/arch/x86_64/include/x86_64/memory/mmu.hpp
@@ -1,9 +1,9 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP
+#ifndef TEACHOS_X86_64_MEMORY_MMU_HPP
+#define TEACHOS_X86_64_MEMORY_MMU_HPP
-#include "arch/memory/paging/virtual_page.hpp"
+#include "kapi/memory/address.hpp"
-namespace teachos::arch::kernel::cpu
+namespace teachos::memory::x86_64
{
/**
* @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained
@@ -12,7 +12,7 @@ namespace teachos::arch::kernel::cpu
* @param address Memory address, which will be used to determine the contained page and flush the TLB entry for
* that page.
*/
- auto tlb_flush(memory::paging::virtual_address address) -> void;
+ auto tlb_flush(linear_address address) -> void;
/**
* @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables.
@@ -22,6 +22,6 @@ namespace teachos::arch::kernel::cpu
*/
auto tlb_flush_all() -> void;
-} // namespace teachos::arch::kernel::cpu
+} // namespace teachos::memory::x86_64
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/page_table.hpp b/arch/x86_64/include/x86_64/memory/page_table.hpp
new file mode 100644
index 0000000..71ba5b7
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/page_table.hpp
@@ -0,0 +1,341 @@
+#ifndef TEACHOS_X86_64_PAGE_TABLE_HPP
+#define TEACHOS_X86_64_PAGE_TABLE_HPP
+
+#include "kapi/memory.hpp"
+
+#include "x86_64/memory/page_utilities.hpp"
+
+#include <kstd/ext/bitfield_enum>
+
+#include <array>
+#include <bit>
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+namespace teachos::memory::x86_64
+{
+
+ //! A table containing page mapping entries.
+ //!
+ //! Page tables exist in a multi-level hierarchy and are used to map pages (virtual memory) onto frames (physical
+ //! memory). Conceptually, pages represent the data found in a virtual address space, while frames represent their
+ //! storage. Only a level 1 page table maps an actual page onto a frame. All other page tables on higher levels do not
+ //! map payload pages, but rather their subordinate page tables.
+ struct page_table
+ {
+ //! An entry in a page table.
+ //!
+ //! A page table entry is a combination of a frame number and a set of flags that determine the properties and
+ //! access rights to a mapped page. Entries at a higher level in the page hierarchy do not map a page directly,
+ //! unless that page is marked as huge on the relevant level, but rather map the next lower page table.
+ struct entry
+ {
+ //! Flags marking the state and configuration of an entry.
+ //!
+ //! An entry in a page table may have any combination of these flags active at the same time. The final flags of a
+ //! page are determined as the strictest combination (logical AND) of all flags along the hierarchy.
+ //!
+ //! @note This is a bitfield enum as defined by kstd::ext::bitfield_enum.
+ enum struct flags : std::uint64_t
+ {
+ empty = 0,
+ present = 1uz << 0, //!< The page is mapped.
+ writable = 1uz << 1, //!< The page is writable.
+ user_accessible = 1uz << 2, //!< The page is accessible in user mode.
+ write_through = 1uz << 3, //!< Any writes to the page must immediately hit memory.
+ disable_cache = 1uz << 4, //!< Any writes to the page must never be cached.
+ accessed = 1uz << 5, //!< The page was accessed.
+ dirty = 1uz << 6, //!< The page was written to.
+ huge_page = 1uz << 7, //!< The page is huge.
+ global = 1uz << 8, //!< The TLB entry for this page must not be flushed on context switches.
+ no_execute = 1uz << 63, //!< The data in this page must not be executed.
+ };
+
+ //! Construct an empty entry.
+ entry() = default;
+
+ //! Clear this entry, ensuring all information is set to zero.
+ //!
+ //! This effectively marks the page represented by this entry as not present. In addition, it also removes any
+ //! information about the frame referenced by this entry.
+ auto clear() noexcept -> void;
+
+ //! Check if the page represented by this entry is present.
+ //!
+ //! @note This function does not attempt to walk the page table hierarchy, but only performs a local check. This
+ //! means, that if the page is not mapped at a lower level, this will not be detected.
+ //!
+ //! @return @p true iff. the page is present at this level, @p false otherwise.
+ [[nodiscard]] auto present() const noexcept -> bool;
+
+ //! Check if the page represented by this entry is a huge page.
+ //!
+ //! @note The effective size of the page depends on the level of the page table containing this entry.
+ //!
+ //! @return @p true iff. the page is marked as being huge, @p false otherwise.
+ [[nodiscard]] auto huge() const noexcept -> bool;
+
+ //! Get all flags present in this entry.
+ //!
+ //! @return The flags that are currently set on this entry.
+ [[nodiscard]] auto all_flags() const noexcept -> flags;
+
+ //! Set all flags of this entry.
+ //!
+ //! @param flags The flags to apply to this entry.
+ auto all_flags(flags flags) noexcept -> void;
+
+ //! Add the given flags to the flags of this entry.
+ //!
+ //! @param rhs The flags to add to this entry's flags.
+ //! @return A reference to this entry.
+ auto operator|=(flags rhs) noexcept -> entry &;
+
+ //! Get the frame number associated with this entry, if the referenced page is present.
+ //!
+ //! @return an engaged std::optional iff. this entry maps a page, std::nullopt otherwise.
+ [[nodiscard]] auto frame() const noexcept -> std::optional<frame>;
+
+ //! Map this entry.
+ //!
+ //! @param frame The frame to map in this entry.
+ //! @param flags The flags to apply to this entry.
+ auto frame(struct frame frame, flags flags) noexcept -> void;
+
+ private:
+ //! A mask to retrieve, or exclude, the frame number from the raw entry.
+ //!
+ //! Page table entries in x86_64 are a compacted combination of the relevant flags and the frame number. This mask
+ //! represents the bits that make up the frame number in an entry.
+ constexpr auto static frame_number_mask{0x000f'ffff'ffff'f000uz};
+
+ //! The raw entry bytes.
+ //!
+ //! @see entry::frame_number_mask
+ std::uint64_t m_raw{};
+ };
+
+ //! The maximum number of entries in this table.
+ constexpr auto static entry_count{page::size / sizeof(entry)};
+
+ //! Get the entry at the given index.
+ //!
+ //! @warning This function will panic if the entry index is out of bounds.
+ //!
+ //! @param index The index of the desired entry.
+ //! @return A reference to the entry at the given index.
+ [[nodiscard]] auto operator[](std::size_t index) -> entry &;
+
+ //! @copydoc page_table::operator[]
+ [[nodiscard]] auto operator[](std::size_t index) const -> entry const &;
+
+ //! Clear the entire page table.
+ //!
+ //! This function effectively marks the page table as not mapping any pages.
+ auto clear() noexcept -> void;
+
+ //! Check if the page table is empty.
+ //!
+ //! @return @p true iff. this page table has no entries marked present, @p false otherwise.
+ [[nodiscard]] auto empty() const noexcept -> bool;
+
+ private:
+ std::array<entry, entry_count> m_entries{};
+ };
+
+ //! A recursively mapped page table.
+ //!
+ //! A page table in which at least one entry maps the same table. Recursive page tables allow for easy access to other
+ //! tables within the page mapping hierarchy, without having to map them prior to access, through careful construction
+ //! of linear addresses that pass through the same index multiple times.
+ template<std::size_t Level>
+ requires(Level > 0uz && Level < 5uz)
+ struct recursive_page_table : page_table
+ {
+ constexpr auto static next_level = Level - 1uz;
+ constexpr auto static recursive_index = 0776uz;
+
+ //! Get the next lower lever table.
+ //!
+ //! @param self The object type of this object.
+ //! @param index The index corresponding to the desired page map.
+ //! @return An engaged std::optional holding a pointer to the next lower page table iff. the next lower page table
+ //! at the desired index is present, std::nullopt otherwise.
+ [[nodiscard]] auto next(this auto && self, std::size_t index) noexcept
+ requires(next_level > 1)
+ {
+ return self.next_address(index).transform([](auto address) -> auto {
+ auto table_pointer = std::bit_cast<recursive_page_table<next_level> *>(address);
+ return &std::forward_like<decltype(self)>(*table_pointer);
+ });
+ }
+
+ //! @copydoc recursive_page_table::next
+ //!
+ //! @note This overload returns a non-hierarchical, or leaf, page table
+ [[nodiscard]] auto next(this auto && self, std::size_t index) noexcept
+ requires(next_level == 1)
+ {
+ return self.next_address(index).transform([](auto address) -> auto {
+ auto table_pointer = std::bit_cast<page_table *>(address);
+ return &std::forward_like<decltype(self)>(*table_pointer);
+ });
+ }
+
+ [[nodiscard]] auto translate(linear_address address) const -> std::optional<physical_address>
+ requires(Level == 4)
+ {
+ auto offset = address.raw() % page::size;
+ return translate(page::containing(address)).transform([offset](auto frame) -> auto {
+ return physical_address{frame.start_address().raw() + offset};
+ });
+ }
+
+ [[nodiscard]] auto translate(page page) const -> std::optional<frame>
+ requires(Level == 4)
+ {
+ auto pml3 = next(pml_index<4>(page));
+
+ if (!pml3)
+ {
+ return std::nullopt;
+ }
+
+ auto handle_huge_page = [&] -> std::optional<frame> {
+ auto pml3_entry = pml3.transform([&](auto pml3) -> auto { return (*pml3)[pml_index<3>(page)]; });
+ if (!pml3_entry)
+ {
+ return std::nullopt;
+ }
+ else if (pml3_entry->huge())
+ {
+ auto pml3_entry_frame = *pml3_entry->frame();
+ return frame{pml3_entry_frame.number() + pml_index<2>(page) * entry_count + pml_index<1>(page)};
+ }
+
+ auto pml2 = (*pml3)->next(pml_index<3>(page));
+ auto pml2_entry = pml2.transform([&](auto pml2) -> auto { return (*pml2)[pml_index<2>(page)]; });
+ if (!pml2_entry)
+ {
+ return std::nullopt;
+ }
+ else if (pml2_entry->huge())
+ {
+ auto pml2_entry_frame = *pml2_entry->frame();
+ return frame{pml2_entry_frame.number() + pml_index<1>(page)};
+ }
+
+ return std::nullopt;
+ };
+
+ return pml3.and_then([&](auto pml3) -> auto { return pml3->next(pml_index<3>(page)); })
+ .and_then([&](auto pml2) -> auto { return pml2->next(pml_index<2>(page)); })
+ .and_then([&](auto pml1) -> auto { return (*pml1)[pml_index<1>(page)].frame(); })
+ .or_else(handle_huge_page);
+ }
+
+ private:
+ //! The number of address bits used to represent the page index per level.
+ constexpr auto static level_bits = 9;
+ //! The highest address bit.
+ constexpr auto static high_bit = 48;
+ //! The number of bits representing the offset into a page.
+ constexpr auto static offset_bits = 12;
+
+ //! Calculate the recursive address of the next lower page table.
+ //!
+ //! @param index The index of the desired page table.
+ //! @return An engaged std::optional holding the address of the new lower page table iff. the next lower page table
+ //! at the desired index is present, std::nullopt otherwise.
+ [[nodiscard]] auto next_address(std::size_t index) const noexcept -> std::optional<std::uintptr_t>
+ {
+ if (auto entry = (*this)[index]; entry.present() && !entry.huge())
+ {
+ auto this_address = std::bit_cast<std::uintptr_t>(this);
+ auto next_address = (this_address << level_bits) | 1uz << high_bit | (index << offset_bits);
+ return next_address;
+ }
+
+ return std::nullopt;
+ }
+ };
+
+} // namespace teachos::memory::x86_64
+
+namespace kstd::ext
+{
+ template<>
+ struct is_bitfield_enum<teachos::memory::x86_64::page_table::entry::flags> : std::true_type
+ {
+ };
+} // namespace kstd::ext
+
+namespace teachos::memory::x86_64
+{
+
+ constexpr auto to_mapper_flags(page_table::entry::flags flags) -> page_mapper::flags
+ {
+ using table_flags = page_table::entry::flags;
+ using mapper_flags = page_mapper::flags;
+
+ auto result = mapper_flags{};
+
+ if ((flags & table_flags::no_execute) == table_flags::empty)
+ {
+ result |= mapper_flags::executable;
+ }
+
+ if ((flags & table_flags::writable) != table_flags::empty)
+ {
+ result |= mapper_flags::writable;
+ }
+
+ if ((flags & table_flags::disable_cache) != table_flags::empty)
+ {
+ result |= mapper_flags::uncached;
+ }
+
+ if ((flags & table_flags::user_accessible) == table_flags::empty)
+ {
+ result |= mapper_flags::supervisor_only;
+ }
+
+ return result;
+ }
+
+ constexpr auto to_table_flags(page_mapper::flags flags) -> page_table::entry::flags
+ {
+ using table_flags = page_table::entry::flags;
+ using mapper_flags = page_mapper::flags;
+
+ auto result = table_flags{};
+
+ if ((flags & mapper_flags::executable) == mapper_flags::empty)
+ {
+ result |= table_flags::no_execute;
+ }
+
+ if ((flags & mapper_flags::writable) != mapper_flags::empty)
+ {
+ result |= table_flags::writable;
+ }
+
+ if ((flags & mapper_flags::uncached) != mapper_flags::empty)
+ {
+ result |= table_flags::disable_cache;
+ }
+
+ if ((flags & mapper_flags::supervisor_only) != mapper_flags::empty)
+ {
+ result |= table_flags::user_accessible;
+ }
+
+ return result;
+ }
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/page_utilities.hpp b/arch/x86_64/include/x86_64/memory/page_utilities.hpp
new file mode 100644
index 0000000..efd1b80
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/page_utilities.hpp
@@ -0,0 +1,22 @@
+#ifndef TEACHOS_X86_64_PAGE_UTILITIES_HPP
+#define TEACHOS_X86_64_PAGE_UTILITIES_HPP
+
+#include "kapi/memory.hpp"
+
+#include <cstddef>
+
+namespace teachos::memory::x86_64
+{
+
+ template<std::size_t Level>
+ requires(Level > 0uz && Level < 5uz)
+ constexpr auto pml_index(page page) noexcept -> std::size_t
+ {
+ constexpr auto shift_width = (Level - 1) * 9;
+ constexpr auto index_mask = 0x1ffuz;
+ return page.number() >> shift_width & index_mask;
+ }
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/paging_root.hpp b/arch/x86_64/include/x86_64/memory/paging_root.hpp
new file mode 100644
index 0000000..47ee2f9
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/paging_root.hpp
@@ -0,0 +1,27 @@
+#ifndef TEACHOS_X86_64_PAGING_ROOT_HPP
+#define TEACHOS_X86_64_PAGING_ROOT_HPP
+
+#include "x86_64/memory/page_table.hpp"
+
+namespace teachos::memory::x86_64
+{
+
+ //! The active, recursively mapped, root map (e.g. PML4)
+ struct paging_root : recursive_page_table<4>
+ {
+ auto static get() -> paging_root *;
+
+ paging_root(paging_root const &) = delete;
+ paging_root(paging_root &&) = delete;
+ auto operator=(paging_root const &) -> paging_root & = delete;
+ auto operator=(paging_root &&) -> paging_root & = delete;
+
+ ~paging_root() = delete;
+
+ private:
+ paging_root() = default;
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp b/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp
new file mode 100644
index 0000000..dc52065
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp
@@ -0,0 +1,23 @@
+#ifndef TEACHOS_X86_64_RECURSIVE_PAGE_MAPPER_HPP
+#define TEACHOS_X86_64_RECURSIVE_PAGE_MAPPER_HPP
+
+#include "kapi/memory.hpp"
+
+namespace teachos::memory::x86_64
+{
+
+ struct recursive_page_mapper : page_mapper
+ {
+ explicit recursive_page_mapper(frame_allocator & allocator);
+
+ auto map(page page, frame frame, flags flags) -> std::byte * override;
+ auto unmap(page page) -> void override;
+ auto try_unmap(page page) noexcept -> bool override;
+
+ private:
+ frame_allocator * m_allocator;
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/memory/region_allocator.hpp b/arch/x86_64/include/x86_64/memory/region_allocator.hpp
new file mode 100644
index 0000000..84b7a94
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/region_allocator.hpp
@@ -0,0 +1,79 @@
+#ifndef TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP
+#define TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP
+
+#include "kapi/memory/address.hpp"
+#include "kapi/memory/frame.hpp"
+#include "kapi/memory/frame_allocator.hpp"
+
+#include <multiboot2/information.hpp>
+
+#include <optional>
+#include <utility>
+
+namespace teachos::memory::x86_64
+{
+ //! A simple, memory-region based frame allocator.
+ //!
+ //! This frame allocator linearly allocates frames that are in available memory regions. It automatically skips any
+ //! frames occupied by the kernel image or any bootloader provided data.
+ //!
+ //! @note This allocator will never release frames.
+ struct region_allocator final : frame_allocator
+ {
+ struct memory_information
+ {
+ //! The memory range occupied by the loaded kernel image.
+ //!
+ //! This includes all sections that are marked as occupying space in the kernel executable. The internal structure
+ //! of this area is more described in a more fine-grained manner by the ELF symbol information provided in the
+ //! Multiboot2 information by the loader.
+ std::pair<physical_address, physical_address> image_range;
+
+ //! The memory range occupied by the loader supplied Multiboot2 information structure.
+ //!
+ //! In general, this information is allocated somewhere in the range of the loaded image, but the loader protocol
+ //! does not guarantee this. It is thus imperative to be able to handle the cases where the loader chooses to
+ //! allocate the information structure outside of the image range.
+ std::pair<physical_address, physical_address> mbi_range;
+
+ //! The loader supplied map of memory regions.
+ //!
+ //! These include available, unavailable, and reclaimable regions. In general, only frames that are located in
+ //! non-reserved (as in available) regions should be allocated for page storage.
+ multiboot2::memory_map memory_map;
+ };
+
+ using region = multiboot2::memory_map::region;
+
+ //! Construct a new allocator using the provided memory information
+ //!
+ //! @param information The description of the detected memory regions as well as regions that are already occupied.
+ explicit region_allocator(memory_information const & information);
+
+ //! @copydoc frame_allocator::allocate
+ //!
+ //! @note As long as free frames are available, successive calls to this implementation are guaranteed to yield
+ //! frames in ascending order.
+ auto allocate() noexcept -> std::optional<frame> override;
+
+ //! @copydoc frame_allocator::release
+ //!
+ //! @note This implementation will never actually release any frames.
+ auto release(frame frame) -> void override;
+
+ private:
+ //! Find the next memory area and write it into current_area.
+ auto choose_next_area() -> void;
+
+ frame m_next_frame; //!< The next available frame.
+ std::optional<region> m_current_region; //!< The memory region currently used for allocation
+ multiboot2::memory_map m_memory_map; //!< The boot loader supplied memory map.
+ frame m_kernel_start; //!< The start of the kernel image in physical memory.
+ frame m_kernel_end; //!< The end of the kernel image in physical memory.
+ frame m_multiboot_start; //!< The start of the Multiboot2 information in physical memory.
+ frame m_multiboot_end; //!< The end of the Multiboot2 information in physical memory.
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/include/x86_64/memory/scoped_mapping.hpp b/arch/x86_64/include/x86_64/memory/scoped_mapping.hpp
new file mode 100644
index 0000000..835e2df
--- /dev/null
+++ b/arch/x86_64/include/x86_64/memory/scoped_mapping.hpp
@@ -0,0 +1,66 @@
+#ifndef TEACHOS_X86_64_SCOPED_MAPPING_HPP
+#define TEACHOS_X86_64_SCOPED_MAPPING_HPP
+
+#include "kapi/memory.hpp"
+
+#include "x86_64/memory/page_table.hpp"
+
+namespace teachos::memory::x86_64
+{
+
+ //! A page mapping that, if established, maps a given frame to a given unused page, unmapping it on destruction. It
+ //! allows for an easy way to quickly map a page that is not required to be mapped forever. When mapping a frame, new
+ //! page tables may be allocated. On destruction, these pages tables, or rather their respective frames, will be
+ //! released again.
+ struct scoped_mapping
+ {
+ //! Copying a scoped mapping would be meaningless.
+ scoped_mapping(scoped_mapping const &) noexcept = delete;
+
+ //! Adopt an existing scoped mapping, transferring mapping ownership to this new object.
+ scoped_mapping(scoped_mapping &&) noexcept;
+
+ //! Construct a new scoped mapping, which can be used to map a frame to the given unused page.
+ //! @param page An unused page. If the page is already mapped, this constructor will panic.
+ //! @param mapper The page mapper to use for mapping and unmapping of the page.
+ explicit scoped_mapping(page page, page_mapper & mapper);
+
+ //! Unmap the mapped frame if one was mapped.
+ //! @note Any page tables that were allocated to support the mapping will be released.
+ ~scoped_mapping() noexcept;
+
+ //! Copying a scoped mapping would be meaningless.
+ auto operator=(scoped_mapping const &) -> scoped_mapping = delete;
+
+ //! Adopt an existing scoped mapping, swapping mapping ownerships between the objects.
+ auto operator=(scoped_mapping &&) noexcept -> scoped_mapping &;
+
+ //! Map the given frame with the given flags.
+ //! @note If a mapping has already been established, this function will panic
+ //! @param frame A frame to map.
+ //! @param flags The flags, besides the present flag, to apply to the mapping.
+ //! @return A pointer to the first byte of the mapped frame.
+ auto map(frame frame, page_table::entry::flags flags) -> std::byte *;
+
+ //! Map the given frame, returning a typed pointer.
+ template<typename DataType>
+ auto map_as(frame frame, page_table::entry::flags flags) -> DataType *
+ {
+ return std::bit_cast<DataType *>(map(frame, flags));
+ }
+
+ //! Unmap the mapped frame.
+ //! @note If no frame was ever mapped, this function will panic.
+ auto unmap() -> void;
+
+ friend auto swap(scoped_mapping & lhs, scoped_mapping & rhs) -> void;
+
+ private:
+ page m_page;
+ page_mapper * m_mapper;
+ bool m_mapped;
+ };
+
+} // namespace teachos::memory::x86_64
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/vga/crtc.hpp b/arch/x86_64/include/x86_64/vga/crtc.hpp
new file mode 100644
index 0000000..d4b4f51
--- /dev/null
+++ b/arch/x86_64/include/x86_64/vga/crtc.hpp
@@ -0,0 +1,39 @@
+#ifndef TEACHOS_X86_64_VGA_IO_HPP
+#define TEACHOS_X86_64_VGA_IO_HPP
+
+#include "x86_64/device_io/port_io.hpp"
+
+#include <cstddef>
+
+namespace teachos::vga::x86_64::crtc
+{
+ namespace io = io::x86_64;
+
+ /**
+ * @brief The address port of the CRT Controller.
+ */
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
+ using address = io::port<0x3d4, std::byte, io::port_write>;
+
+ /**
+ * @brief The data port of the CRT Controller.
+ */
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
+ using data = io::port<0x3d5, std::byte, io::port_read, io::port_write>;
+
+ namespace registers
+ {
+ /**
+ * @brief The address of the Cursor Start register of the CRTC.
+ */
+ [[maybe_unused]] constexpr auto cursor_start = std::byte{0x0a};
+
+ /**
+ * @brief The address of the Cursor End register of the CRTC.
+ */
+ [[maybe_unused]] constexpr auto cursor_end = std::byte{0x0b};
+ } // namespace registers
+
+} // namespace teachos::vga::x86_64::crtc
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/x86_64/vga/text.hpp b/arch/x86_64/include/x86_64/vga/text.hpp
new file mode 100644
index 0000000..bb593e7
--- /dev/null
+++ b/arch/x86_64/include/x86_64/vga/text.hpp
@@ -0,0 +1,178 @@
+#ifndef TEACHOS_X86_64_VIDEO_VGA_TEXT_HPP
+#define TEACHOS_X86_64_VIDEO_VGA_TEXT_HPP
+
+#include "kapi/cio.hpp"
+
+#include <cstdint>
+#include <span>
+#include <string_view>
+
+namespace teachos::vga::x86_64::text
+{
+ /**
+ * @brief The colors available in the standard VGA text mode.
+ */
+ enum struct color : std::uint8_t
+ {
+ black, ///< Equivalent to HTML color \#000000.
+ blue, ///< Equivalent to HTML color \#0000AA.
+ green, ///< Equivalent to HTML color \#00AA00.
+ cyan, ///< Equivalent to HTML color \#00AAAA.
+ red, ///< Equivalent to HTML color \#AA0000.
+ purple, ///< Equivalent to HTML color \#AA00AA.
+ brown, ///< Equivalent to HTML color \#AA5500.
+ gray, ///< Equivalent to HTML color \#AAAAAA.
+ };
+
+ /**
+ * @brief The foreground color modification flag.
+ */
+ enum struct foreground_flag : bool
+ {
+ none, ///< Apply no flag e.g., keep color as is.
+ intense, ///< Make the color more intense (usually brighter).
+ };
+
+ /**
+ * @brief The background color modification flag.
+ */
+ enum struct background_flag : bool
+ {
+ none, ///< Apply no flag e.g., keep color as is.
+ blink_or_bright, ///< Make the cell blink or more intense, dependent on the VGA configuration.
+ };
+
+ /**
+ * @brief The VGA text mode attribute.
+ *
+ * @note In the text mode of VGA, every code point being presented is followed by an attribute description. This
+ * allows for the modification of how the relevant "cell" is presented.
+ *
+ * @see vga::text::foreground_flag
+ * @see vga::text::background_flag
+ */
+ struct attribute
+ {
+ color foreground_color : 3; ///< The foreground color of the cell, e.g. the color of the code point.
+ enum foreground_flag foreground_flag : 1; ///< The foreground color modification flag of the cell.
+ color background_color : 3; ///< The background color of the cell.
+ enum background_flag background_flag : 1; ///< The background color modification flag of the cell.
+ };
+
+ static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte.");
+
+ /**
+ * @brief Commonly used VGA text mode attributes.
+ */
+ namespace common_attributes
+ {
+ /**
+ * @brief Make the affected cell display with a gray foreground and black background.
+ */
+ [[maybe_unused]] constexpr auto gray_on_black = attribute{.foreground_color = color::gray,
+ .foreground_flag = foreground_flag::none,
+ .background_color = color::black,
+ .background_flag = background_flag::none};
+
+ /**
+ * @brief Make the affected cell display with a green foreground and black background.
+ */
+ [[maybe_unused]] constexpr auto green_on_black = attribute{.foreground_color = color::green,
+ .foreground_flag = foreground_flag::none,
+ .background_color = color::black,
+ .background_flag = background_flag::none};
+
+ /**
+ * @brief Make the affected cell display with a green foreground and black background.
+ */
+ [[maybe_unused]] constexpr auto red_on_black = attribute{.foreground_color = color::red,
+ .foreground_flag = foreground_flag::none,
+ .background_color = color::black,
+ .background_flag = background_flag::none};
+
+ /**
+ * @brief Make the affected cell display with a white (gray + intense) foreground and red background.
+ */
+ [[maybe_unused]] constexpr auto white_on_red = attribute{.foreground_color = color::gray,
+ .foreground_flag = foreground_flag::intense,
+ .background_color = color::red,
+ .background_flag = background_flag::none};
+ } // namespace common_attributes
+
+ struct device final : teachos::cio::output_device
+ {
+ device();
+
+ /**
+ * @brief Clear the VGA text mode buffer.
+ *
+ * @note This function also resets the text mode buffer pointer.
+ *
+ * @param attribute The attribute to "clear" the screen with.
+ */
+ auto clear(attribute attribute = common_attributes::gray_on_black) -> void;
+
+ /**
+ * @brief Enable or disable the VGA text mode cursor.
+ *
+ * @param enabled Whether or not to enable the cursors.
+ */
+ auto cursor(bool enabled) -> void;
+
+ auto write(std::string_view text) -> void override
+ {
+ write(text, common_attributes::green_on_black);
+ }
+ auto writeln(std::string_view text) -> void override
+ {
+ writeln(text, common_attributes::green_on_black);
+ }
+ auto write_error(std::string_view text) -> void override
+ {
+ write(text, common_attributes::red_on_black);
+ }
+ auto writeln_error(std::string_view text) -> void override
+ {
+ writeln(text, common_attributes::red_on_black);
+ }
+
+ private:
+ using glyph = std::pair<char, std::byte>;
+
+ /**
+ * @brief Move the cursor to a new line, scrolling the buffer if necessary.
+ */
+ auto newline() -> void;
+
+ /**
+ * @brief Write a string of code points to the VGA text buffer.
+ *
+ * @note This function also updates the text mode buffer pointer.
+ *
+ * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer.
+ * @param attribute The attribute to apply to the written sequence of code points.
+ * @see vga::text::attribute
+ */
+ auto write(std::string_view code_points, attribute attribute) -> void;
+
+ auto write(char code_point, attribute attribute) -> void;
+
+ /**
+ * @brief Write a string of code points followed by a newline to the VGA text buffer.
+ *
+ * @note This function also updates the text mode buffer pointer.
+ *
+ * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer.
+ * @param attribute The attribute to apply to the written sequence of code points.
+ * @see vga::text::attribute
+ */
+ auto writeln(std::string_view code_points, attribute attribute) -> void;
+
+ std::span<glyph> static const buffer;
+
+ std::size_t m_position{};
+ };
+
+} // namespace teachos::vga::x86_64::text
+
+#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP \ No newline at end of file