aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-01-16 17:39:23 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-01-16 17:39:23 +0100
commit7ba274d0838e5cd4e48e85f81557bbb837ed4349 (patch)
treeb792f550634b856e3401ea42dd0ee7089494be28 /arch
parentf7fc4cb67c8c7c6ec1833f6ac6f0ad3a2837251d (diff)
downloadkernel-7ba274d0838e5cd4e48e85f81557bbb837ed4349.tar.xz
kernel-7ba274d0838e5cd4e48e85f81557bbb837ed4349.zip
x86_64/cpu: port GDT reload procedure
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/cpu/global_descriptor_table.hpp91
-rw-r--r--arch/x86_64/include/arch/cpu/segment_descriptor.hpp61
-rw-r--r--arch/x86_64/include/arch/cpu/task_state_segment.hpp30
-rw-r--r--arch/x86_64/kapi/system.cpp110
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp104
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp93
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp37
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp41
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp73
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp74
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp32
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp97
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp20
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp26
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp109
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp11
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp41
-rw-r--r--arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp30
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/gdtr.cpp19
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/msr.cpp31
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/segment_register.cpp98
23 files changed, 291 insertions, 991 deletions
diff --git a/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp b/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp
new file mode 100644
index 0000000..402c87d
--- /dev/null
+++ b/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp
@@ -0,0 +1,91 @@
+#ifndef TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP
+#define TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP
+
+#include "kapi/memory.hpp"
+
+#include "arch/cpu/segment_descriptor.hpp"
+
+#include <algorithm>
+#include <array>
+#include <bit>
+#include <concepts>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+namespace arch::cpu
+{
+
+ template<std::size_t Size>
+ struct global_descriptor_table;
+
+ struct [[gnu::packed]] global_descriptor_table_pointer
+ {
+ template<std::size_t GdtSize>
+ global_descriptor_table_pointer(global_descriptor_table<GdtSize> const & gdt)
+ : size{GdtSize * sizeof(segment_descriptor) - 1}
+ , address{kapi::memory::physical_address{std::bit_cast<std::uintptr_t>(&gdt)}.raw()}
+ {}
+
+ auto load() -> void
+ {
+ asm volatile("lgdt %0" : : "m"(*this));
+ }
+
+ std::uint16_t size{};
+ std::uint64_t address{};
+ };
+
+ static_assert(sizeof(global_descriptor_table_pointer) == sizeof(std::uint16_t) + sizeof(std::uint64_t));
+
+ template<std::size_t SizeInBytes>
+ struct global_descriptor_table
+ {
+ template<std::derived_from<segment_descriptor>... SegmentDescriptors>
+ constexpr global_descriptor_table(SegmentDescriptors const &... descriptors)
+ : m_descriptors{}
+ {
+ auto descriptor_data = std::array{
+ std::pair{std::bit_cast<std::byte const *>(&descriptors), sizeof(descriptors)}
+ ...
+ };
+ auto written_size = 0uz;
+ std::ranges::for_each(descriptor_data, [&written_size, this](auto entry) {
+ std::ranges::copy(entry.first, entry.first + entry.second, m_descriptors.begin() + written_size);
+ written_size += entry.second;
+ });
+ }
+
+ auto load(std::size_t code_segment_index, std::size_t data_segment_index) const -> void
+ {
+ auto pointer = global_descriptor_table_pointer{*this};
+ pointer.load();
+
+ asm volatile("push %0\n"
+ "lea 1f(%%rip), %%rax\n"
+ "push %%rax\n"
+ "lretq\n"
+ "1:\n"
+ "mov %1, %%rax\n"
+ "mov %%rax, %%ss\n"
+ "mov %%rax, %%ds\n"
+ "mov %%rax, %%es\n"
+ "mov %%rax, %%fs\n"
+ "mov %%rax, %%gs\n"
+ :
+ : "X"(code_segment_index * sizeof(segment_descriptor)),
+ "X"(data_segment_index * sizeof(segment_descriptor))
+ : "rax");
+ }
+
+ private:
+ std::array<std::byte, SizeInBytes> m_descriptors;
+ };
+
+ template<std::derived_from<segment_descriptor>... SegmentDescriptors>
+ global_descriptor_table(SegmentDescriptors const &... descriptors)
+ -> global_descriptor_table<(sizeof(SegmentDescriptors) + ...)>;
+
+} // namespace arch::cpu
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/cpu/segment_descriptor.hpp b/arch/x86_64/include/arch/cpu/segment_descriptor.hpp
new file mode 100644
index 0000000..9570670
--- /dev/null
+++ b/arch/x86_64/include/arch/cpu/segment_descriptor.hpp
@@ -0,0 +1,61 @@
+#ifndef TEACHOS_X86_64_SEGMENT_DESCRIPTOR_HPP
+#define TEACHOS_X86_64_SEGMENT_DESCRIPTOR_HPP
+
+#include <cstdint>
+
+namespace arch::cpu
+{
+
+ //! The type of segment described by a segment_descriptor.
+ enum struct segment_type : std::uint8_t
+ {
+ //! A system (TSS or LDT) segment
+ system = 0,
+ //! A code or data segment
+ code_or_data = 1,
+ };
+
+ //! The granularity of a segment described by a segment_descriptor
+ enum struct segment_granularity : std::uint8_t
+ {
+ //! The limit of the segment is defined in bytes.
+ byte = 0,
+ //! The limit of the segment is defined in pages (4KiB)
+ page = 1,
+ };
+
+ //! An entry in a segment descriptor table
+ struct segment_descriptor
+ {
+ std::uint64_t limit_low : 16;
+ std::uint64_t base_low : 24;
+ bool accessed : 1;
+ bool read_write : 1;
+ bool direction_or_conforming : 1;
+ bool executable : 1;
+ segment_type type : 1;
+ std::uint64_t privilege_level : 2;
+ bool present : 1;
+ std::uint64_t limit_high : 4;
+ std::uint64_t : 1;
+ bool long_mode : 1;
+ bool protected_mode : 1;
+ segment_granularity granularity : 1;
+ std::uint64_t base_high : 8;
+ };
+
+ static_assert(sizeof(segment_descriptor) == sizeof(std::uint64_t));
+ static_assert(alignof(segment_descriptor) == alignof(std::uint64_t));
+
+ struct system_segment_descriptor : segment_descriptor
+ {
+ std::uint64_t base_extended : 32;
+ std::uint64_t : 32;
+ };
+
+ static_assert(sizeof(system_segment_descriptor) == 2 * sizeof(std::uint64_t));
+ static_assert(alignof(system_segment_descriptor) == alignof(segment_descriptor));
+
+} // namespace arch::cpu
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/cpu/task_state_segment.hpp b/arch/x86_64/include/arch/cpu/task_state_segment.hpp
new file mode 100644
index 0000000..57729dd
--- /dev/null
+++ b/arch/x86_64/include/arch/cpu/task_state_segment.hpp
@@ -0,0 +1,30 @@
+#ifndef TEACHOS_X86_64_TASK_STATE_SEGMENT_HPP
+#define TEACHOS_X86_64_TASK_STATE_SEGMENT_HPP
+
+#include <cstdint>
+
+namespace arch::cpu
+{
+
+ struct [[gnu::packed]] task_state_segment
+ {
+ 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 arch::cpu
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/kapi/system.cpp b/arch/x86_64/kapi/system.cpp
index 5bcae4d..ca4418e 100644
--- a/arch/x86_64/kapi/system.cpp
+++ b/arch/x86_64/kapi/system.cpp
@@ -1,14 +1,122 @@
#include "kapi/system.hpp"
+#include "arch/cpu/global_descriptor_table.hpp"
+#include "arch/cpu/segment_descriptor.hpp"
+#include "arch/cpu/task_state_segment.hpp"
+
#include <kstd/print>
+#include <bit>
+#include <cstdint>
+
namespace kapi::system
{
+ namespace
+ {
+ constexpr auto gdt_null_descriptor = arch::cpu::segment_descriptor{};
+
+ constexpr auto gdt_kernel_code_descriptor = arch::cpu::segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = true,
+ .type = arch::cpu::segment_type::code_or_data,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = true,
+ .protected_mode = false,
+ .granularity = arch::cpu::segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_kernel_data_descriptor = arch::cpu::segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = true,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = arch::cpu::segment_type::code_or_data,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = false,
+ .protected_mode = true,
+ .granularity = arch::cpu::segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_user_code_descriptor = arch::cpu::segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = true,
+ .type = arch::cpu::segment_type::code_or_data,
+ .privilege_level = 3,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = true,
+ .protected_mode = false,
+ .granularity = arch::cpu::segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_user_data_descriptor = arch::cpu::segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = true,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = arch::cpu::segment_type::code_or_data,
+ .privilege_level = 3,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = false,
+ .protected_mode = false,
+ .granularity = arch::cpu::segment_granularity::page,
+ .base_high = 0,
+ };
+ } // namespace
+
auto memory_initialized() -> void
{
+ auto static tss = arch::cpu::task_state_segment{};
+ auto static tss_descriptor = arch::cpu::system_segment_descriptor{
+ {
+ .limit_low = (sizeof(tss) - 1) & 0xffff, // NOLINT(readability-magic-numbers)
+ .base_low = std::bit_cast<std::uintptr_t>(&tss) & 0xffffff, // NOLINT(readability-magic-numbers)
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = arch::cpu::segment_type::system,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = ((sizeof(tss) - 1) >> 16) & 0xf, // NOLINT(readability-magic-numbers)
+ .long_mode = false,
+ .protected_mode = false,
+ .granularity = arch::cpu::segment_granularity::byte,
+ .base_high = (std::bit_cast<std::uintptr_t>(&tss) >> 24) & 0xff, // NOLINT(readability-magic-numbers)
+ },
+ (std::bit_cast<std::uintptr_t>(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
+ };
+
+ auto static gdt = arch::cpu::global_descriptor_table{
+ gdt_null_descriptor, gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
+ gdt_user_code_descriptor, gdt_user_data_descriptor, tss_descriptor,
+ };
+
+ kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
+ gdt.load(1, 2);
+
kstd::println("[x86_64:SYS] TODO: initialize Interrupt Descriptor Table.");
- kstd::println("[x86_64:SYS] TODO: reload Global Descriptor Table.");
}
} // namespace kapi::system \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
deleted file mode 100644
index 7450330..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp
deleted file mode 100644
index e24b988..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp
deleted file mode 100644
index 44f2692..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp
deleted file mode 100644
index 292ff70..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp
deleted file mode 100644
index 933fb4d..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp
deleted file mode 100644
index 40bcc8a..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp
deleted file mode 100644
index 8770b81..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp b/arch/x86_64/pre/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp
deleted file mode 100644
index d4aa5e8..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/kernel/cpu/gdtr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/gdtr.hpp
deleted file mode 100644
index 68b950d..0000000
--- a/arch/x86_64/pre/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/pre/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/segment_register.hpp
deleted file mode 100644
index a236452..0000000
--- a/arch/x86_64/pre/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/pre/src/context_switching/segment_descriptor_table/access_byte.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp
deleted file mode 100644
index fcc72cf..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/access_byte.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- access_byte::access_byte(uint8_t flags)
- : _flags(flags)
- {
- // Nothing to do.
- }
-
- auto access_byte::contains_flags(std::bitset<8U> other) const -> bool
- {
- return (std::bitset<8U>{_flags} & other) == other;
- }
-
- auto access_byte::operator|=(std::bitset<8U> other) -> void
- {
- _flags |= other.to_ulong();
- }
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp
deleted file mode 100644
index ad1366a..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- gdt_flags::gdt_flags(uint8_t flags, std::bitset<20U> limit)
- : _limit_2(limit.to_ulong() >> 16U)
- , _flags(flags)
- {
- // Nothing to do.
- }
-
- auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool
- {
- return (std::bitset<4U>{_flags} & other) == other;
- }
-
- auto gdt_flags::get_limit() const -> std::bitset<4U>
- {
- return std::bitset<4U>{_limit_2};
- }
-
- auto gdt_flags::operator|=(std::bitset<4U> other) -> void
- {
- _flags |= other.to_ulong();
- }
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp
deleted file mode 100644
index 1c4729f..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp"
-
-#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp"
-#include "arch/exception_handling/assert.hpp"
-#include "arch/kernel/cpu/gdtr.hpp"
-#include "arch/kernel/cpu/tr.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- namespace
- {
- auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_byte access_level)
- -> segment_descriptor_base
- {
- constexpr uint64_t BASE = 0x0;
- constexpr std::bitset<20U> LIMIT{0xFFFFF};
- gdt_flags flags{gdt_flags::GRANULARITY, LIMIT};
-
- access_level |= access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT;
- if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT)
- {
- flags |= gdt_flags::LONG_MODE;
- access_level |= access_byte::CODE_SEGMENT | access_byte::READABLE;
- }
- else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT)
- {
- access_level |= access_byte::WRITABLE;
- }
-
- segment_descriptor_base const segment_descriptor_base{access_level, flags, BASE, LIMIT};
- return segment_descriptor_base;
- }
-
- auto create_tss_descriptor(task_state_segment * tss) -> segment_descriptor_extension
- {
- constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1;
- access_byte const tss_access_byte{access_byte::PRESENT | access_byte::DESCRIPTOR_LEVEL_KERNEL |
- access_byte::TASK_STATE_SEGMENT_AVAILABLE};
- gdt_flags const tss_gdt_flags{0U, TSS_LIMIT};
- segment_descriptor_extension const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast<uint64_t>(tss),
- TSS_LIMIT};
- return tss_descriptor;
- }
-
- auto create_gdt() -> global_descriptor_table
- {
- segment_descriptor_base const null_segment{0};
- segment_descriptor_base const kernel_code_segment =
- create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL);
- segment_descriptor_base const kernel_data_segment =
- create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL);
- segment_descriptor_base const user_code_segment =
- create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER);
- segment_descriptor_base const user_data_segment =
- create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER);
-
- // Task State Segment needs to be kept alive
- auto static tss = new task_state_segment();
- segment_descriptor_extension const tss_descriptor = create_tss_descriptor(tss);
-
- global_descriptor_table global_descriptor_table{null_segment,
- kernel_code_segment,
- kernel_data_segment,
- user_code_segment,
- user_data_segment,
- tss_descriptor.get_first_gdt_entry(),
- tss_descriptor.get_second_gdt_entry()};
- return global_descriptor_table;
- }
- } // namespace
-
- auto get_or_create_gdt() -> global_descriptor_table &
- {
- // Global Descriptor Table needs to be kept alive
- global_descriptor_table static gdt = create_gdt();
- return gdt;
- }
-
- auto update_gdtr() -> void
- {
- decltype(auto) gdt = get_or_create_gdt();
-
- // Calculate the size of the gdt in bytes - 1. This subtraction occurs because the maximum value of Size is 65535,
- // while the GDT can be up to 65536 bytes in length (8192 entries). Further, no GDT can have a size of 0 bytes.
- uint16_t gdt_size = static_cast<uint16_t>((gdt.size() * sizeof(segment_descriptor_base)) - 1);
- global_descriptor_table_pointer gdt_pointer{gdt_size, gdt.data()};
- kernel::cpu::load_global_descriptor_table(gdt_pointer);
-
- auto const stored_gdt_pointer = kernel::cpu::store_global_descriptor_table();
- arch::exception_handling::assert(
- gdt_pointer == stored_gdt_pointer,
- "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value.");
- }
-
- auto update_tss_register() -> void
- {
- decltype(auto) gdt = get_or_create_gdt();
-
- // Load task state segment descriptor from the last element in the global descriptor table, done by calculating
- // offset in bytes to the start of the segment descriptor (5 * 8) = 40
- uint16_t tss_selector = (gdt.size() * sizeof(segment_descriptor_base)) - sizeof(segment_descriptor_extension);
- kernel::cpu::load_task_register(tss_selector);
-
- auto const stored_task_register = kernel::cpu::store_task_register();
- arch::exception_handling::assert(tss_selector == stored_task_register,
- "[Global Descriptor Table] Loaded TR value is not the same as the stored value.");
- }
-
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp
deleted file mode 100644
index 79088b8..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length, uint64_t * address)
- : table_length(table_length)
- , address(address)
- {
- // Nothing to do.
- }
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp
deleted file mode 100644
index c3a03fc..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- segment_descriptor_base::segment_descriptor_base(uint64_t flags)
- : _limit_1(flags)
- , _base_1(flags >> 16U)
- , _access(flags >> 40U)
- , _flag(flags >> 52U, flags >> 48U)
- , _base_2(flags >> 56U)
- {
- // Nothing to do.
- }
-
- segment_descriptor_base::segment_descriptor_base(access_byte access_byte, gdt_flags flags, uint32_t base,
- std::bitset<20U> limit)
- : _limit_1(limit.to_ulong())
- , _base_1(base)
- , _access(access_byte)
- , _flag(flags)
- , _base_2(base >> 24U)
- {
- // Nothing to do
- }
-
- auto segment_descriptor_base::get_segment_type() const -> segment_descriptor_type
- {
- if (!_access.contains_flags(access_byte::CODE_OR_DATA_SEGMENT))
- {
- return segment_descriptor_type::SYSTEM_SEGMENT;
- }
- return _access.contains_flags(access_byte::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT
- : segment_descriptor_type::DATA_SEGMENT;
- }
-
- segment_descriptor_base::operator uint64_t() const
- {
- return *reinterpret_cast<uint64_t const *>(this);
- }
-
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp
deleted file mode 100644
index 5ea0d8a..0000000
--- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp"
-
-namespace teachos::arch::context_switching::segment_descriptor_table
-{
- segment_descriptor_extension::segment_descriptor_extension(uint128_t flags)
- : _base(flags)
- , _base_3(flags >> 64U)
- {
- // Nothing to do.
- }
-
- segment_descriptor_extension::segment_descriptor_extension(access_byte access_byte, gdt_flags flags, uint64_t base,
- std::bitset<20U> limit)
- : _base(access_byte, flags, base, limit)
- , _base_3(base >> 32U)
- {
- // Nothing to do
- }
-
- auto segment_descriptor_extension::get_first_gdt_entry() const -> segment_descriptor_base
- {
- return _base;
- }
-
- auto segment_descriptor_extension::get_second_gdt_entry() const -> uint64_t
- {
- return _base_3;
- }
-
-} // namespace teachos::arch::context_switching::segment_descriptor_table
diff --git a/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp b/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp
deleted file mode 100644
index 74a4e1c..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "arch/kernel/cpu/gdtr.hpp"
-
-#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- auto store_global_descriptor_table() -> context_switching::segment_descriptor_table::global_descriptor_table_pointer
- {
- context_switching::segment_descriptor_table::global_descriptor_table_pointer current_value{};
- asm("sgdt %[output]" : [output] "=m"(current_value));
- return current_value;
- }
-
- auto load_global_descriptor_table(
- context_switching::segment_descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void
- {
- asm volatile("lgdt %[input]" : /* no output from call */ : [input] "m"(gdt_pointer));
- }
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/pre/src/kernel/cpu/msr.cpp b/arch/x86_64/pre/src/kernel/cpu/msr.cpp
deleted file mode 100644
index 9d6a318..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/msr.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "arch/kernel/cpu/msr.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- namespace
- {
- constexpr auto IA32_EFER_ADDRESS = 0xC000'0080;
- }
-
- auto read_msr(uint32_t msr) -> uint64_t
- {
- uint32_t low, high;
- asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
- return (static_cast<uint64_t>(high) << 32) | low;
- }
-
- auto write_msr(uint32_t msr, uint64_t value) -> void
- {
- uint32_t low = value;
- uint32_t high = value >> 32;
- asm volatile("wrmsr"
- : /* no output from call */
- : "c"(msr), "a"(low), "d"(high));
- }
-
- auto set_efer_bit(efer_flags flag) -> void
- {
- auto const efer = read_msr(IA32_EFER_ADDRESS);
- write_msr(IA32_EFER_ADDRESS, static_cast<std::underlying_type<efer_flags>::type>(flag) | efer);
- }
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp b/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp
deleted file mode 100644
index b08c9c4..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "arch/kernel/cpu/segment_register.hpp"
-
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-#include "arch/exception_handling/assert.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- auto reload_data_segment_registers() -> void
- {
- asm volatile("xor %%rax, %%rax\n"
- "mov %%rax, %%ss\n"
- "mov %%rax, %%ds\n"
- "mov %%rax, %%es\n"
- "mov %%rax, %%fs\n"
- "mov %%rax, %%gs\n"
- : /* no output from call */
- : /* no input to call */
- : "rax");
- }
-
- auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) -> void
- {
- asm volatile("xor %%rax, %%rax\n"
- "mov %[input], %%ax\n"
- "mov %%rax, %%ds\n"
- "mov %%rax, %%es\n"
- "mov %%rax, %%fs\n"
- "mov %%rax, %%gs\n"
- : /* no output from call */
- : [input] "m"(data_segment)
- : "rax");
- }
-
- auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector
- {
- context_switching::interrupt_descriptor_table::segment_selector current_value{};
- asm volatile("mov %%cs, %[output]" : [output] "=r"(current_value));
- return current_value;
- }
-
- auto validate_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment)
- -> void
- {
- context_switching::interrupt_descriptor_table::segment_selector ss{};
- context_switching::interrupt_descriptor_table::segment_selector ds{};
- context_switching::interrupt_descriptor_table::segment_selector es{};
- context_switching::interrupt_descriptor_table::segment_selector fs{};
- context_switching::interrupt_descriptor_table::segment_selector gs{};
-
- asm volatile(
- "mov %%ss, %[ss_output]\n"
- "mov %%ds, %[ds_output]\n"
- "mov %%es, %[es_output]\n"
- "mov %%fs, %[fs_output]\n"
- "mov %%gs, %[gs_output]\n"
- : [ss_output] "=r"(ss), [ds_output] "=r"(ds), [es_output] "=r"(es), [fs_output] "=r"(fs), [gs_output] "=r"(gs));
-
- auto result = (ss == ds && ss == es && ss == fs && ss == gs);
- exception_handling::assert(result, "[Segment Register] Values in data register are not the same.");
- result = (ss == data_segment);
- exception_handling::assert(
- result, "[Segment Register] Expected Data Segment is not the same as the value in the Stack Segment register.");
- }
-
- auto validate_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector code_segment)
- -> void
- {
- auto const cs = read_code_segment_register();
- exception_handling::assert(
- cs == code_segment,
- "[Segment Register] Expected Code Segment is not the same as the value in 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
- {
- validate_data_segment_registers(data_segment);
- validate_code_segment_register(code_segment);
- }
-
- 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
- {
- asm volatile("mov %%rsp, %%rax\n"
- "push %[data_segment]\n"
- "push %%rax\n"
- "pushfq\n"
- "push %[code_segment]\n"
- "mov %[return_function], %%rax\n"
- "push %%rax\n"
- "iretq\n"
- : /* no output from call */
- : [data_segment] "m"(data_segment), [code_segment] "m"(code_segment), [return_function] "r"(address)
- : "rax");
- }
-
-} // namespace teachos::arch::kernel::cpu