diff options
10 files changed, 141 insertions, 46 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3717788..daf87b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,7 @@ target_link_libraries("_kernel" PRIVATE "teachos::memory" "teachos::exception" "teachos::shared" + "teachos::context_switching" ) #[============================================================================[ 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 index d1b579d..dc4de03 100644 --- 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 @@ -19,8 +19,7 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - PRESENT = 1U << 0U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. + CODE_OR_DATA_SEGMENT = 1U << 0U, ///< Defines a system segment (if 0) or a code/data segment (if 1). ACCESS_LEVEL_KERNEL = 0, ///< Highest privileged level used by the kernel to allow for full access of resources. ACCESS_LEVEL_ADMIN = 2, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more @@ -28,17 +27,23 @@ namespace teachos::arch::context_switching::descriptor_table ACCESS_LEVEL_PRIVILEGED_USER = 4, ///< 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 = 6, ///< Restricts access to only application and their specific memory. - CODE_OR_DATA_SEGMENT = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 3U, ///< 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 Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. + * @param flags Left-most four bits of the access_byte. + * @param type_field Right-most four bits of the access_byte representing the type_field. */ - access_byte(uint8_t flags); + access_byte(uint8_t flags, uint8_t type_field); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -67,8 +72,8 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(access_byte const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. - type_field _type; ///< Field specifying the type of the segment descriptor and its settings. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. + type_field _type = {}; ///< Field specifying the type of the segment descriptor and its settings. }; } // namespace teachos::arch::context_switching::descriptor_table 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 index bc6ecb7..f27284e 100644 --- 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 @@ -18,21 +18,26 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - GRANULARITY = 1U << 0U, ///< Indicates the size the Limit value in the segement descriptor is scaled by 1 Byte - ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. - DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and - ///< operands. Enable for 32 bit, 16 bit 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. + 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. - LENGTH = 1U << 2U ///< 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, otherwis they are executed in compatability 32-bit mode. If bis is set the - ///< DEFAULT_LENGTH bis needs to be 0 + 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 Actual value read from the elf section header, which should be converted into a std::bitset, to @@ -61,7 +66,7 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(gdt_flags const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table 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 index 364e546..b5697e3 100644 --- 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 @@ -17,6 +17,11 @@ namespace teachos::arch::context_switching::descriptor_table struct 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 @@ -33,16 +38,24 @@ namespace teachos::arch::context_switching::descriptor_table 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; private: - uint32_t _reserved; - access_byte _access; - gdt_flags _flag; - uint64_t _base; - std::bitset<20U> _limit; + uint32_t _reserved = {}; + access_byte _access = {}; + gdt_flags _flag = {}; + uint64_t _base = {}; + std::bitset<20U> _limit = {}; }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp index da61d38..3822f9c 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp @@ -18,22 +18,22 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - CODE_SEGMENT = 1U << 0U, ///< Further defines the actual type of the segment. If enabled this segment is a code - ///< segment, otherwise its a data segment. - EXPAND_UP = 1U << 1U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the - ///< data segment expands downwards, otherwise it expands upwards. - CONFORMING = - 1U << 1U, ///< 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. - WRITABLE = 1U << 2U, ///< 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 << 2U, ///< 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. ACCESSED = 1U - << 3U, ///< Whether the segment has been accessed since the last time the operating system has cleared the + << 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. @@ -45,6 +45,11 @@ namespace teachos::arch::context_switching::descriptor_table }; /** + * @brief Default Constructor. + */ + type_field() = default; + + /** * @brief Constructor. * * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to @@ -72,7 +77,7 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(type_field const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index b8bedf3..112af57 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -18,7 +18,7 @@ namespace teachos::arch::stl struct vector { /** - * @brief Defaulted constructor. Initalizes empty vector. + * @brief Default Constructor. */ vector() = default; diff --git a/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp b/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp index 7a2b0b0..4e5459f 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp @@ -2,9 +2,9 @@ namespace teachos::arch::context_switching::descriptor_table { - access_byte::access_byte(uint8_t flags) + access_byte::access_byte(uint8_t flags, uint8_t type_field) : _flags(flags) - , _type(flags) + , _type(type_field) { // Nothing to do. } diff --git a/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp b/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp index 8fbf869..65f2e90 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp @@ -5,7 +5,7 @@ namespace teachos::arch::context_switching::descriptor_table { gdt_flags::gdt_flags(uint8_t flags) - : _flags(flags << 5U) + : _flags(flags) { // Nothing to do. } diff --git a/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp b/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp index 57564f2..ab8eaba 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp @@ -4,7 +4,7 @@ namespace teachos::arch::context_switching::descriptor_table { segment_descriptor::segment_descriptor(uint128_t flags) : _reserved(flags >> 96U) - , _access((flags >> 40U) << 80U) + , _access((flags >> 44U) << 80U, (flags >> 40U) << 84U) , _flag((flags >> 52U) << 72U) , _base(((flags >> 64U) << 32U) << 32U | ((flags >> 56U) << 64U) << 24U | (flags >> 16U) << 88U) , _limit(((flags >> 48U) << 72U) << 16U | flags << 112U) @@ -12,13 +12,29 @@ namespace teachos::arch::context_switching::descriptor_table // Nothing to do. } + segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, + std::bitset<20U> limit) + : _reserved(0U) + , _access(access_byte) + , _flag(flags) + , _base(base) + , _limit(limit) + { + // Nothing to do + } + auto segment_descriptor::get_segment_type() const -> segment_descriptor_type { if (!_access.contains_flags(access_byte::CODE_OR_DATA_SEGMENT)) { return segment_descriptor_type::SYSTEM_SEGMENT; } - return _access.get_type_field().contains_flags(type_field::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT - : segment_descriptor_type::DATA_SEGMENT; + + if (_access.get_type_field().contains_flags(type_field::CODE_SEGMENT)) + { + return segment_descriptor_type::CODE_SEGMENT; + } + + return segment_descriptor_type::DATA_SEGMENT; } } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index 472aed5..d3938ed 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -1,9 +1,11 @@ #include "arch/kernel/main.hpp" +#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" #include "arch/memory/heap/bump_allocator.hpp" #include "arch/memory/heap/global_heap_allocator.hpp" #include "arch/memory/main.hpp" #include "arch/memory/multiboot/reader.hpp" +#include "arch/stl/vector.hpp" #include "arch/video/vga/text.hpp" namespace teachos::arch::kernel @@ -57,5 +59,53 @@ namespace teachos::arch::kernel memory::heap::global_heap_allocator::register_heap_allocator(memory::heap::heap_allocator_type::LINKED_LIST); heap_test(); + + using context_switching::descriptor_table::access_byte; + using context_switching::descriptor_table::gdt_flags; + using context_switching::descriptor_table::segment_descriptor; + using context_switching::descriptor_table::segment_descriptor_type; + using context_switching::descriptor_table::type_field; + + segment_descriptor null_segment{0}; + + // Kernel space code segment + access_byte kernel_code_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | + access_byte::CODE_OR_DATA_SEGMENT, + type_field::CODE_SEGMENT | type_field::READABLE}; + gdt_flags kernel_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH}; + segment_descriptor kernel_code_segment{kernel_code_access_byte, kernel_code_gdt_flags, 0, 0xFFFFF}; + + // Kernel space data segment + access_byte kernel_data_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | + access_byte::CODE_OR_DATA_SEGMENT, + type_field::WRITABLE}; + gdt_flags kernel_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND}; + segment_descriptor kernel_data_segment{kernel_data_access_byte, kernel_data_gdt_flags, 0, 0xFFFFF}; + + // User space code segment + access_byte user_code_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_USER | + access_byte::CODE_OR_DATA_SEGMENT, + type_field::CODE_SEGMENT | type_field::READABLE}; + gdt_flags user_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH}; + segment_descriptor user_code_segment{user_code_access_byte, user_code_gdt_flags, 0, 0xFFFFF}; + + // User space data segment + access_byte user_data_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_USER | + access_byte::CODE_OR_DATA_SEGMENT, + type_field::WRITABLE}; + gdt_flags user_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND}; + segment_descriptor user_data_segment{user_data_access_byte, user_data_gdt_flags, 0, 0xFFFFF}; + + stl::vector<segment_descriptor> global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment}; + + decltype(auto) x = global_descriptor_table.at(1); + if (global_descriptor_table.size() == 0) + { + } + if (x.get_segment_type() == segment_descriptor_type::CODE_SEGMENT) + { + } + video::vga::text::write("GDT FILLED", video::vga::text::common_attributes::green_on_black); } } // namespace teachos::arch::kernel |
