From ccb47845d99e098c183f596cd1a3eb1db5c676da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 25 Mar 2025 12:04:43 +0000 Subject: Adjust file structure and fix compilation issues --- arch/x86_64/CMakeLists.txt | 18 ++-- .../descriptor_table/access_byte.hpp | 97 ---------------------- .../descriptor_table/gate_descriptor.hpp | 15 ---- .../descriptor_table/gdt_flags.hpp | 86 ------------------- .../descriptor_table/global_descriptor_table.hpp | 55 ------------ .../global_descriptor_table_pointer.hpp | 42 ---------- .../descriptor_table/initialization.hpp | 23 ----- .../interrupt_descriptor_table.hpp | 14 ---- .../interrupt_descriptor_table_pointer.hpp | 42 ---------- .../descriptor_table/segment_descriptor.hpp | 71 ---------------- .../descriptor_table/segment_descriptor_type.hpp | 27 ------ .../descriptor_table/task_state_segment.hpp | 32 ------- .../interrupt_descriptor_table/gate_descriptor.hpp | 15 ++++ .../interrupt_descriptor_table.hpp | 14 ++++ .../interrupt_descriptor_table_pointer.hpp | 42 ++++++++++ .../x86_64/include/arch/context_switching/main.hpp | 23 +++++ .../segment_descriptor_table/access_byte.hpp | 97 ++++++++++++++++++++++ .../segment_descriptor_table/gdt_flags.hpp | 86 +++++++++++++++++++ .../global_descriptor_table.hpp | 55 ++++++++++++ .../global_descriptor_table_pointer.hpp | 42 ++++++++++ .../segment_descriptor.hpp | 71 ++++++++++++++++ .../segment_descriptor_type.hpp | 27 ++++++ .../task_state_segment.hpp | 32 +++++++ arch/x86_64/include/arch/kernel/cpu/gdtr.hpp | 9 +- arch/x86_64/include/arch/kernel/cpu/idtr.hpp | 8 +- arch/x86_64/include/arch/kernel/cpu/tr.hpp | 2 - .../descriptor_table/access_byte.cpp | 15 ---- .../descriptor_table/gate_descriptor.cpp | 5 -- .../descriptor_table/gdt_flags.cpp | 18 ---- .../descriptor_table/global_descriptor_table.cpp | 92 -------------------- .../global_descriptor_table_pointer.cpp | 12 --- .../descriptor_table/initialization.cpp | 38 --------- .../interrupt_descriptor_table.cpp | 10 --- .../interrupt_descriptor_table_pointer.cpp | 13 --- .../descriptor_table/segment_descriptor.cpp | 35 -------- .../interrupt_descriptor_table/gate_descriptor.cpp | 5 ++ .../interrupt_descriptor_table.cpp | 10 +++ .../interrupt_descriptor_table_pointer.cpp | 13 +++ arch/x86_64/src/context_switching/main.cpp | 36 ++++++++ .../segment_descriptor_table/access_byte.cpp | 15 ++++ .../segment_descriptor_table/gdt_flags.cpp | 18 ++++ .../global_descriptor_table.cpp | 92 ++++++++++++++++++++ .../global_descriptor_table_pointer.cpp | 12 +++ .../segment_descriptor.cpp | 35 ++++++++ arch/x86_64/src/kernel/cpu/gdtr.cpp | 11 ++- arch/x86_64/src/kernel/cpu/idtr.cpp | 9 +- arch/x86_64/src/kernel/main.cpp | 4 +- 47 files changed, 768 insertions(+), 775 deletions(-) delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/context_switching/main.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/initialization.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp create mode 100644 arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp create mode 100644 arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp create mode 100644 arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp create mode 100644 arch/x86_64/src/context_switching/main.cpp create mode 100644 arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp create mode 100644 arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp create mode 100644 arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp create mode 100644 arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp create mode 100644 arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp (limited to 'arch') diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index a435ef9..cf92feb 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -92,15 +92,15 @@ target_sources("_exception" PRIVATE #]============================================================================] target_sources("_context" PRIVATE - "src/context_switching/descriptor_table/access_byte.cpp" - "src/context_switching/descriptor_table/gate_descriptor.cpp" - "src/context_switching/descriptor_table/gdt_flags.cpp" - "src/context_switching/descriptor_table/global_descriptor_table.cpp" - "src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp" - "src/context_switching/descriptor_table/initialization.cpp" - "src/context_switching/descriptor_table/interrupt_descriptor_table.cpp" - "src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp" - "src/context_switching/descriptor_table/segment_descriptor.cpp" + "src/context_switching/segment_descriptor_table/access_byte.cpp" + "src/context_switching/segment_descriptor_table/gdt_flags.cpp" + "src/context_switching/segment_descriptor_table/global_descriptor_table.cpp" + "src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp" + "src/context_switching/segment_descriptor_table/segment_descriptor.cpp" + "src/context_switching/main.cpp" + "src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp" + "src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp" + "src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp" ) #[============================================================================[ diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp deleted file mode 100644 index 646c2ca..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ /dev/null @@ -1,97 +0,0 @@ - -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP - -#include -#include - -namespace teachos::arch::context_switching::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 std::bitset 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). - ACCESS_LEVEL_KERNEL = - 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. - ACCESS_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. - ACCESS_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. - ACCESS_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 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<8U> 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==(access_byte const & other) const -> bool = default; - - private: - uint8_t _flags = {}; ///< Underlying bitset used to read the flags from. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp deleted file mode 100644 index f410219..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP - -namespace teachos::arch::context_switching::descriptor_table -{ - struct [[gnu::packed]] gate_descriptor - { - /** - * @brief Default Constructor. - */ - gate_descriptor() = default; - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp deleted file mode 100644 index de41762..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP - -#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" - -#include - -namespace teachos::arch::context_switching::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 std::bitset and the meaning when they are set. - */ - enum bitset : uint8_t - { - LENGTH = 1U << 0U, ///< 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 bis - ///< is set the DEFAULT_LENGTH bis needs to be 0 - UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 - ///< GiB, 4 KiB otherwise. - STACK_POINTER_SIZE = 1U << 1U, ///< 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 << 1U, ///< Indicates the default length for code segments with effective addresses and - ///< operands. Enable for 32 bit, 16 bit otherwise. - GRANULARITY = 1U << 2U, ///< 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 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<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; - - private: - uint8_t _limit_2 : 4 = {}; - uint8_t _flags : 4 = {}; ///< Underlying bitset used to read the flags from. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp deleted file mode 100644 index 75e1e9d..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP - -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" -#include "arch/context_switching/descriptor_table/task_state_segment.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - enum class access_level - { - KERNEL, - USER - }; - - /** - * @brief Creates a generic segment_descriptor from the passed arguments. - * - * @param segment_descriptor_type Defines the type of the segment descriptor. - * @param access_level Defines the segment descriptor access level (KERNEL or USER). - * @return Created segment_descriptor. - */ - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) - -> segment_descriptor; - - /** - * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: - * - * - Kernel Code Segment - * - Kernel Data Segment - * - User Code Segment - * - User Data Segment - * - * @return Copy of the created global_descriptor_table. - */ - auto create_global_descriptor_table() -> global_descriptor_table; - - /** - * @brief Creates a task_state_segment segment_descriptor on the heap. - * - * @param tss task_state_segment whose pointer is used in the segment_descriptor - * @return Created segment_descriptor. - */ - auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; - - /** - * @brief Initializes the global_descriptor_table and task_state_segment by loading them - * in the GDTR and TR registers respectively. - * - * @return Reference to the created global_descriptor_table. - */ - auto initialize_global_descriptor_table() -> global_descriptor_table &; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp deleted file mode 100644 index ed17be3..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP - -#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" -#include "arch/stl/vector.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - typedef stl::vector global_descriptor_table; - - /** - * @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, global_descriptor_table * 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. - global_descriptor_table * address = {}; ///< Non-owning pointer to the GDT base address. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp deleted file mode 100644 index c587000..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP - -#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" -#include "arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief TODO - * - */ - struct descriptor_tables - { - global_descriptor_table & gdt; ///< Reference to the global descriptor table. - interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table. - }; - - auto initialize_descriptor_tables() -> descriptor_tables; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp deleted file mode 100644 index c63932d..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP - -namespace teachos::arch::context_switching::descriptor_table -{ - struct interrupt_descriptor_table - { - }; - - auto initialize_interrupt_descriptor_table() -> void; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp deleted file mode 100644 index e8935f4..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP - -#include "arch/context_switching/descriptor_table/gate_descriptor.hpp" -#include "arch/stl/vector.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - typedef stl::vector interrupt_descriptor_table; - - /** - * @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, interrupt_descriptor_table * 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. - interrupt_descriptor_table address = {}; ///< Non-owning pointer to the IDT base address. - }; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp deleted file mode 100644 index 8714eb8..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP - -#include "arch/context_switching/descriptor_table/access_byte.hpp" -#include "arch/context_switching/descriptor_table/gdt_flags.hpp" -#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" - -namespace teachos::arch::context_switching::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 - { - /** - * @brief Default Constructor. - */ - segment_descriptor() = default; - - /** - * @brief Constructor. - * - * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved - * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment - * descriptor. - * - 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(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(access_byte access_byte, gdt_flags flags, uint64_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 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 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) - uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) - uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp deleted file mode 100644 index 4815fca..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP - -#include - -namespace teachos::arch::context_switching::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::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp deleted file mode 100644 index 1e306af..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP - -#include - -namespace teachos::arch::context_switching::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::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_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 new file mode 100644 index 0000000..2252b7b --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -0,0 +1,15 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + struct [[gnu::packed]] gate_descriptor + { + /** + * @brief Default Constructor. + */ + gate_descriptor() = default; + }; +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP 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..ac52a39 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + struct interrupt_descriptor_table + { + }; + + auto initialize_interrupt_descriptor_table() -> void; + +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_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..de40f90 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp @@ -0,0 +1,42 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP + +#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp" +#include "arch/stl/vector.hpp" + +#include + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + typedef stl::vector interrupt_descriptor_table; + + /** + * @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, interrupt_descriptor_table * 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. + interrupt_descriptor_table * address = {}; ///< Non-owning pointer to the IDT base address. + }; + +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_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..ef642d6 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -0,0 +1,23 @@ +#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 TODO + * + */ + 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. + }; + + auto initialize_descriptor_tables() -> descriptor_tables; + +} // 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..bbf3f49 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp @@ -0,0 +1,97 @@ + +#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 +#include + +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 std::bitset 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). + ACCESS_LEVEL_KERNEL = + 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. + ACCESS_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. + ACCESS_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. + ACCESS_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 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<8U> 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==(access_byte const & other) const -> bool = default; + + private: + uint8_t _flags = {}; ///< Underlying bitset 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 new file mode 100644 index 0000000..2ce5286 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -0,0 +1,86 @@ +#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 + +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 std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + LENGTH = 1U << 0U, ///< 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 bis + ///< is set the DEFAULT_LENGTH bis needs to be 0 + UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 + ///< GiB, 4 KiB otherwise. + STACK_POINTER_SIZE = 1U << 1U, ///< 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 << 1U, ///< Indicates the default length for code segments with effective addresses and + ///< operands. Enable for 32 bit, 16 bit otherwise. + GRANULARITY = 1U << 2U, ///< 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 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<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; + + private: + uint8_t _limit_2 : 4 = {}; + uint8_t _flags : 4 = {}; ///< Underlying bitset 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 new file mode 100644 index 0000000..a111a1f --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -0,0 +1,55 @@ +#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 +{ + enum class access_level + { + KERNEL, + USER + }; + + /** + * @brief Creates a generic segment_descriptor from the passed arguments. + * + * @param segment_descriptor_type Defines the type of the segment descriptor. + * @param access_level Defines the segment descriptor access level (KERNEL or USER). + * @return Created segment_descriptor. + */ + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) + -> segment_descriptor; + + /** + * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: + * + * - Kernel Code Segment + * - Kernel Data Segment + * - User Code Segment + * - User Data Segment + * + * @return Copy of the created global_descriptor_table. + */ + auto create_global_descriptor_table() -> global_descriptor_table; + + /** + * @brief Creates a task_state_segment segment_descriptor on the heap. + * + * @param tss task_state_segment whose pointer is used in the segment_descriptor + * @return Created segment_descriptor. + */ + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; + + /** + * @brief Initializes the global_descriptor_table and task_state_segment by loading them + * in the GDTR and TR registers respectively. + * + * @return Reference to the created global_descriptor_table. + */ + auto initialize_global_descriptor_table() -> global_descriptor_table &; + +} // 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 new file mode 100644 index 0000000..b66070b --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -0,0 +1,42 @@ +#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/context_switching/segment_descriptor_table/segment_descriptor.hpp" +#include "arch/stl/vector.hpp" + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + typedef stl::vector global_descriptor_table; + + /** + * @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, global_descriptor_table * 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. + global_descriptor_table * 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.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp new file mode 100644 index 0000000..7fe4ecb --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp @@ -0,0 +1,71 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_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 +{ + __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 + { + /** + * @brief Default Constructor. + */ + segment_descriptor() = default; + + /** + * @brief Constructor. + * + * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved + * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment + * descriptor. + * - 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(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(access_byte access_byte, gdt_flags flags, uint64_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 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 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) + uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 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_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 new file mode 100644 index 0000000..8770b81 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP + +#include + +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 new file mode 100644 index 0000000..d4aa5e8 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp @@ -0,0 +1,32 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP + +#include + +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/kernel/cpu/gdtr.hpp b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp index f9220b9..68b950d 100644 --- a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" #include #include @@ -14,14 +14,13 @@ namespace teachos::arch::kernel::cpu * * @return Value of GDTR register. */ - auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer; + 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::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) - -> void; + auto load_global_descriptor_table( + context_switching::segment_descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp index 724fbdf..cb800d0 100644 --- a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp @@ -1,26 +1,26 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/interrup