From 7c045d8ded72017ff11fd4b9b02148987b944caf Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 1 May 2025 12:25:40 +0000 Subject: WIP experiment with converting GDT to 8-Byte entries --- .../segment_selector.hpp | 8 ++--- .../global_descriptor_table.hpp | 6 ++-- .../global_descriptor_table_pointer.hpp | 18 +++++++++--- .../segment_descriptor.hpp | 12 ++++++++ .../segment_descriptor_base.hpp | 34 ++++++++++++++++++++++ .../segment_descriptor_extension.hpp | 31 ++++++++++++++++++++ 6 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp (limited to 'arch/x86_64/include') 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 index 7bfb563..8748448 100644 --- 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 @@ -44,17 +44,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table * @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. Because it only - * multiplies by 8, but we are using long mode the constructor additionally multiplies the given value by two. This - * is done because 64-bit segment descriptor are twice as big in size. If we wouldn't multiply by two, index 1 would - * result in the middle between the second part of the null entry and the first part of the code kernel segment and - * therefore be invalid. + * 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 * 2U) + , _index(index) { // Nothing to do. } 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 index bd69a46..84a24a2 100644 --- 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 @@ -12,7 +12,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table * * @return Reference to the created global_descriptor_table. */ - auto get_or_create_global_descriptor_table() -> 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 @@ -21,13 +21,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table * @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_global_descriptor_table_register() -> void; + 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_global_descriptor_table_register() and a far jump has been + * @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_task_state_segment_register() -> void; 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 index 6fac2a0..c54647d 100644 --- 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 @@ -1,14 +1,24 @@ #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/context_switching/segment_descriptor_table/segment_descriptor_base.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp" #include "arch/stl/vector.hpp" #include namespace teachos::arch::context_switching::segment_descriptor_table { - using global_descriptor_table = stl::vector; + struct __attribute__((packed, aligned(8))) global_descriptor_table + { + segment_descriptor_base null; + segment_descriptor_base kernel_code; + segment_descriptor_base kernel_data; + segment_descriptor_base user_code; + segment_descriptor_base user_data; + segment_descriptor_base tss_low; + segment_descriptor_extension tss_high; + }; /** * @brief Represents a pointer to the Global Descriptor Table (GDT). @@ -26,7 +36,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. */ - global_descriptor_table_pointer(uint16_t table_length, segment_descriptor * address); + global_descriptor_table_pointer(uint16_t table_length, seg_desc * address); /** * @brief Defaulted three-way comparsion operator. @@ -35,7 +45,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table private: uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - segment_descriptor * address = {}; ///< Non-owning pointer to the GDT base address. + seg_desc * address = {}; ///< Non-owning pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::segment_descriptor_table 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 index 7fe4ecb..ccd604d 100644 --- 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 @@ -10,6 +10,12 @@ namespace teachos::arch::context_switching::segment_descriptor_table __extension__ typedef __int128 int128_t; __extension__ typedef unsigned __int128 uint128_t; + struct seg_desc + { + private: + uint64_t : 64; ///< Makes sure the struct is 8-Bytes big + }; + /** * @brief Defines helper function for all states and the actual data the segment descriptor can have. */ @@ -44,6 +50,12 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); + auto get_limit_1() -> uint16_t; + auto get_base_1() -> uint32_t; + auto get_access() -> access_byte; + auto get_flag() -> gdt_flags; + auto get_base_2() -> uint64_t; + /** * @brief Calculates the underlying segment type that this segement descriptor is describing. */ diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp new file mode 100644 index 0000000..18c9da1 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp @@ -0,0 +1,34 @@ +#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.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 : seg_desc + { + /** + * @brief Default Constructor. + */ + segment_descriptor_base() = default; + + /** + * @brief Constructor. + */ + segment_descriptor_base(segment_descriptor segment_descriptor); + + private: + 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) + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp new file mode 100644 index 0000000..0b724f2 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp @@ -0,0 +1,31 @@ +#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.hpp" + +#include + +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_extension : seg_desc + { + /** + * @brief Default Constructor. + */ + segment_descriptor_extension() = default; + + /** + * @brief Constructor. + */ + segment_descriptor_extension(segment_descriptor segment_descriptor); + + private: + 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_EXTENSION_HPP -- cgit v1.2.3