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/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/interrupt_handling/generic_interrupt_handler.hpp34
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/call.hpp30
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/control_register.hpp (renamed from arch/x86_64/include/arch/memory/cpu/control_register.hpp)10
-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.hpp (renamed from arch/x86_64/include/arch/memory/cpu/msr.hpp)10
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/segment_register.hpp97
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/tlb.hpp (renamed from arch/x86_64/include/arch/memory/cpu/tlb.hpp)12
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/tr.hpp24
-rw-r--r--arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp6
-rw-r--r--arch/x86_64/include/arch/memory/allocator/physical_frame.hpp8
-rw-r--r--arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp50
-rw-r--r--arch/x86_64/include/arch/memory/heap/heap_allocator.hpp6
-rw-r--r--arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp11
-rw-r--r--arch/x86_64/include/arch/memory/heap/memory_block.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp148
-rw-r--r--arch/x86_64/include/arch/memory/main.hpp14
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp8
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/memory_map.hpp6
-rw-r--r--arch/x86_64/include/arch/memory/paging/active_page_table.hpp10
-rw-r--r--arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp45
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_entry.hpp8
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_table.hpp11
-rw-r--r--arch/x86_64/include/arch/memory/paging/virtual_page.hpp4
-rw-r--r--arch/x86_64/include/arch/stl/container.hpp (renamed from arch/x86_64/include/arch/shared/container.hpp)34
-rw-r--r--arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp (renamed from arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp)44
-rw-r--r--arch/x86_64/include/arch/stl/forward_value_iterator.hpp (renamed from arch/x86_64/include/arch/shared/forward_value_iterator.hpp)25
-rw-r--r--arch/x86_64/include/arch/stl/mutex.hpp (renamed from arch/x86_64/include/arch/shared/mutex.hpp)13
-rw-r--r--arch/x86_64/include/arch/stl/shared_pointer.hpp191
-rw-r--r--arch/x86_64/include/arch/stl/stack.hpp212
-rw-r--r--arch/x86_64/include/arch/stl/unique_pointer.hpp158
-rw-r--r--arch/x86_64/include/arch/stl/vector.hpp604
-rw-r--r--arch/x86_64/include/arch/user/main.hpp16
52 files changed, 2718 insertions, 228 deletions
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
new file mode 100644
index 0000000..07110c8
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
@@ -0,0 +1,69 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp"
+#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp"
+#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ __extension__ typedef __int128 int128_t;
+ __extension__ typedef unsigned __int128 uint128_t;
+
+ /**
+ * @brief Defines helper function for all states and the actual data the gate descriptor can have.
+ */
+ struct [[gnu::packed]] gate_descriptor
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ gate_descriptor() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @note Created gate descriptor copies the given bytes into these components ending with a 32 bit reserved
+ * field that has to be used, because the 64-bit gate descriptor needs to be big enough for two 32-bit gate
+ * descriptor.
+ * - 16 bit Segment Selector
+ * - 3 bit Interrupt Stack Table Offset
+ * - 8 bit Type and Flags
+ * - 64 bit Offset
+ *
+ * @param flags Copies the bits set from the given data into the individual components of a gate
+ * descriptor.
+ */
+ explicit gate_descriptor(uint128_t flags);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param selector, ist, flags, offset Copies the bits set from the given data into the individual components of
+ * a gate descriptor.
+ */
+ gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset);
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(gate_descriptor const & other) const -> bool = default;
+
+ private:
+ // The order in private variables starts for the first variable being the rightmost bit.
+ uint16_t _offset_1 = {}; ///< Lower 16 bits of handler function address (0 - 15)
+ segment_selector _selector = {}; ///< Segment selector (16 - 31)
+ ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39)
+ idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47)
+ uint64_t _offset_2 : 48 = {}; ///< Upper 48 bits of handler function address (48 - 95)
+ uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127)
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
new file mode 100644
index 0000000..5104c36
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
@@ -0,0 +1,81 @@
+
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the access byte field of a segment descriptor can
+ * have.
+ */
+ struct [[gnu::packed]] idt_flags
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ INTERRUPT_GATE = 0b01110, ///< The actual type of gate segment is a interrupt gate.
+ TRAP_GATE = 0b01111, ///< The actual type of gate segment is a trap gate.
+ DESCRIPTOR_LEVEL_KERNEL =
+ 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources.
+ DESCRIPTOR_LEVEL_ADMIN =
+ 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_PRIVILEGED_USER =
+ 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory.
+ PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment.
+ ///< Must be set (1) for any valid segment.
+ };
+
+ /**
+ * @brief Default Constructor.
+ */
+ idt_flags() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used
+ * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags
+ * are enabled or not using contains_flags method.
+ */
+ idt_flags(uint8_t flags);
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<8U> other) const -> bool;
+
+ /**
+ * @brief Allows to compare the underlying bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(idt_flags const & other) const -> bool = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<8U> other) -> void;
+
+ private:
+ uint8_t _flags = {}; ///< Underlying bits used to read the flags from.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP \ No newline at end of file
diff --git a/arch/x86_64/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
new file mode 100644
index 0000000..b388e0e
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
@@ -0,0 +1,24 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Updates the IDTR with the created interrupt descriptor table. If it has not been created yet this
+ * method will create it.
+ */
+ auto update_interrupt_descriptor_table_register() -> void;
+
+ /**
+ * @brief Creates the interrupt descriptor table, with the minimum required configuration. If this method is called
+ * more than once, the previously created instance is returned instead.
+ *
+ * @return Reference to the created interrupt_descriptor_table.
+ */
+ auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table &;
+
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
diff --git a/arch/x86_64/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
new file mode 100644
index 0000000..7fe933b
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
@@ -0,0 +1,40 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp"
+#include "arch/stl/vector.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ using interrupt_descriptor_table = stl::vector<gate_descriptor>;
+
+ /**
+ * @brief Represents a pointer to the Interrupt Descriptor Table (IDT).
+ *
+ * This structure is used to store the base address and length of the IDT.
+ */
+ struct [[gnu::packed]] interrupt_descriptor_table_pointer
+ {
+ /**
+ * @brief Default constructor.
+ */
+ interrupt_descriptor_table_pointer() = default;
+
+ /**
+ * @brief Constructor.
+ */
+ interrupt_descriptor_table_pointer(uint16_t table_length, gate_descriptor * address);
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default;
+
+ private:
+ uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1.
+ gate_descriptor * address = {}; ///< Non-owning pointer to the IDT base address.
+ };
+
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
new file mode 100644
index 0000000..e45bcf4
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
@@ -0,0 +1,45 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the interrupt stack table offset field of a gate descriptor can
+ * have. Is automatically increased to one byte in size, to include the following 5 reserved bits in the gate
+ * descriptor.
+ */
+ struct [[gnu::packed]] ist_offset
+ {
+ /**
+ * @brief Default Constructor.
+ */
+ ist_offset() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param offset Offset into the interrupt stack table. A value of of 0 means we do not switch stacks, whereas 1 - 7
+ * mean we switch to the n-th stack in the Interrupt Stack Table, contained in the TSS if the gate descriptor that
+ * contains this field is called.
+ */
+ ist_offset(uint8_t offset);
+
+ /**
+ * @brief Allows to compare the underlying set bits of two instances.
+ *
+ * @param other Other instance that we want to compare with.
+ * @return Whether the underlying set bits of both types are the same.
+ */
+ auto operator==(ist_offset const & other) const -> bool = default;
+
+ private:
+ uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 means we do not switch stacks,
+ ///< whereas 1 - 7 mean we switch to the n-th stack in the Interrupt Stack Table, contained
+ ///< in the TSS if the gate descriptor that contains this field is called.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
new file mode 100644
index 0000000..2a7704e
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
@@ -0,0 +1,105 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ /**
+ * @brief Represents a segment selector in the x86_64 architecture, which points to a valid code segment in the global
+ * descriptor table.
+ *
+ * A segment selector is a 16-bit identifier used to select a segment descriptor
+ * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT).
+ * It contains an index, a table indicator (TI), and a requested privilege level (RPL).
+ */
+ struct [[gnu::packed]] segment_selector
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when they are set.
+ */
+ enum bitset : uint8_t
+ {
+ REQUEST_LEVEL_KERNEL =
+ 0U << 0U, ///< Highest privileged level used by the kernel to allow for full access of resources.
+ REQUEST_LEVEL_ADMIN =
+ 1U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ REQUEST_LEVEL_PRIVILEGED_USER =
+ 2U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
+ ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
+ REQUEST_LEVEL_USER = 3U << 0U, ///< Restricts access to only application and their specific memory.
+ LOCAL_DESCRIPTOR_TABLE = 1U << 2U, ///< Wheter the index referes to an entry in the local or global descriptor
+ ///< table. If enabled the index points to a local descriptor table, if it is
+ ///< cleared it referes to a global descriptor table instead.
+ };
+
+ /**
+ * @brief Default constructor.
+ */
+ segment_selector() = default;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param index Index into the local or global descriptor table. Processor multiplies the index value by 8 (number
+ * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT address.
+ * @param flags Allows to set flags for the flags field using the unscoped enum contained in this class, used to
+ * allow for direct integer conversion.
+ */
+ constexpr segment_selector(uint16_t index, uint8_t flags)
+ : _flags(flags)
+ , _index(index)
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
+ *
+ * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
+ * data. Any additional bits that are set are not relevant.
+ *
+ * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
+ * @return Whether the given flags are a subset or equivalent with the underlying data.
+ */
+ auto contains_flags(std::bitset<3U> other) const -> bool;
+
+ /**
+ * @brief Gets the index into the global descriptor table or the local descriptor table this segment selector is
+ * pointing too.
+ *
+ * @return Underlying value of the index field, bit 3 - 16.
+ */
+ [[gnu::section(".user_text")]]
+ auto get_index() const -> uint16_t;
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ auto operator<=>(segment_selector const & other) const -> std::strong_ordering = default;
+
+ /**
+ * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
+ *
+ * @param other Additional bits that should be set.
+ */
+ auto operator|=(std::bitset<3U> other) -> void;
+
+ /**
+ * @brief Cast the underlying data into a combined 16-bit form, that contains all data.
+ *
+ * @return Underlying value combined into it's full size.
+ */
+ operator uint16_t() const;
+
+ private:
+ uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from.
+ uint16_t _index : 13 =
+ {}; ///< Index into the local or global descriptor table. Processor multiplies the index value by 16 (number of
+ ///< bytes in segment descriptor) and adds the result to the base address.
+ };
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp
new file mode 100644
index 0000000..f8477ea
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/main.hpp
@@ -0,0 +1,51 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
+
+#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp"
+#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp"
+
+namespace teachos::arch::context_switching
+{
+ /**
+ * @brief Contains the references to the tables required for context switching
+ */
+ struct descriptor_tables
+ {
+ segment_descriptor_table::global_descriptor_table & gdt; ///< Reference to the global descriptor table.
+ interrupt_descriptor_table::interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table.
+ };
+
+ /**
+ * @brief Creates the Interrupt Descriptor Table and Global Descriptor Table as a static variable the first time this
+ * method is called and update IDTR and GDTR registers values.
+ *
+ * @note Subsequent calls after the first one, will simply return the previously created tables, but not update the
+ * registers again.
+ *
+ * @return References to the statically created Interrupt Descriptor and Global Descriptor Table.
+ */
+ auto initialize_descriptor_tables() -> descriptor_tables;
+
+ /**
+ * @brief Switches from the current Kernel Mode (Level 0) to User Mode (Level 3). Will simply use predefined Segment
+ * Selectors for the User Data and User Code Segment, which are Index 3 and 4 in the GDT respectively.
+ */
+ auto switch_to_user_mode() -> void;
+
+ /**
+ * @brief Switches from the current Code and Data Segment to the given Code and Data Segment.
+ *
+ * @note This method will additionally call initialize_descriptor_tables, to ensure the GDTR and IDTR have been setup
+ * correctly before attempting to switch the context. This switch is achieved using a far return, which will once
+ * executed call the given void function.
+ *
+ * @param data_segment Data Segment that the SS, DS; ES, FS and GS register will be set too.
+ * @param code_segment Code Segment that the CS register will be set too.
+ * @param return_function Function that will be called once the switch has been achieved.
+ */
+ auto switch_context(interrupt_descriptor_table::segment_selector data_segment,
+ interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void;
+
+} // namespace teachos::arch::context_switching
+
+#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
new file mode 100644
index 0000000..7450330
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp
@@ -0,0 +1,104 @@
+
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP
+
+#include <bitset>
+#include <cstdint>
+
+namespace teachos::arch::context_switching::segment_descriptor_table
+{
+ /**
+ * @brief Defines helper function for all states that the access byte field of a segment descriptor can
+ * have.
+ */
+ struct [[gnu::packed]] access_byte
+ {
+ /**
+ * @brief Possible set bits in our underlying bits and the meaning when th