diff options
Diffstat (limited to 'arch/x86_64')
11 files changed, 106 insertions, 58 deletions
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 index f153e36..2f8e61d 100644 --- 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 @@ -48,13 +48,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table idt_flags(uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @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 - * std::bitset. Any additional bits that are set are not relevant. + * data. 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. + * @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; @@ -66,6 +66,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ 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. }; 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 73cd176..2c90152 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 @@ -51,13 +51,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table segment_selector(uint16_t index, uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @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 - * std::bitset. Any additional bits that are set are not relevant. + * data. 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. + * @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; @@ -66,6 +66,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ 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; + private: uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. uint16_t _index : 13 = 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 index 3d7862c..621b570 100644 --- 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 @@ -71,24 +71,31 @@ namespace teachos::arch::context_switching::segment_descriptor_table access_byte(uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @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 - * std::bitset. Any additional bits that are set are not relevant. + * data. 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. + * @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 std::bitset of two instances. + * @brief Allows to compare the underlying data 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. + * @return Whether the underlying data of both types is the same. */ auto operator==(access_byte const & other) const -> bool = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<8U> other) -> void; + private: uint8_t _flags = {}; ///< Underlying bits used to read the flags from. }; 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 index d8c3cd1..4b84035 100644 --- 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 @@ -50,13 +50,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table 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. + * @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 - * std::bitset. Any additional bits that are set are not relevant. + * data. 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. + * @param other Flags that we want to compare against and check if the underlying data has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying data. */ auto contains_flags(std::bitset<4U> other) const -> bool; @@ -77,6 +77,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ auto operator==(gdt_flags const & other) const -> bool = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<4U> other) -> void; + private: uint8_t _limit_2 : 4 = {}; ///< Second part of the limit field. uint8_t _flags : 4 = {}; ///< Underlying bits used to read the flags from. diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp index e7379ef..d36a4c1 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp @@ -12,4 +12,6 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { return (std::bitset<8U>{_flags} & other) == other; } + + auto idt_flags::operator|=(std::bitset<8U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp index 62b116b..db3351e 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp @@ -6,18 +6,28 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { - auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table & + namespace { - // @MTO: This address resolution is most certainly wrong -> numbers in dbg seem off (offset_3 = 0) - uint64_t offset = reinterpret_cast<uint64_t>(&interrupt_handling::generic_interrupt_handler); - segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; - ist_offset ist{0U}; - idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::PRESENT}; - gate_descriptor descriptor{selector, ist, flags, offset}; + auto create_interrupt_descriptor_table() -> interrupt_descriptor_table + { + // @MTO: This address resolution is most certainly wrong -> numbers in dbg seem off (offset_3 = 0) + uint64_t offset = reinterpret_cast<uint64_t>(&interrupt_handling::generic_interrupt_handler); + segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; + ist_offset ist{0U}; + idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::PRESENT}; + gate_descriptor descriptor{selector, ist, flags, offset}; + + // Interrupt Descriptor Table needs to be kept alive + static interrupt_descriptor_table interrupt_descriptor_table{descriptor}; + return interrupt_descriptor_table; + } + } // namespace + auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table & + { // Interrupt Descriptor Table needs to be kept alive - static interrupt_descriptor_table interrupt_descriptor_table{descriptor}; - return interrupt_descriptor_table; + static interrupt_descriptor_table idt = create_interrupt_descriptor_table(); + return idt; } auto update_interrupt_descriptor_table_register() -> void diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp index 494e50f..62aed9b 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp @@ -13,4 +13,6 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { return (std::bitset<3U>{_flags} & other) == other; } + + auto segment_selector::operator|=(std::bitset<3U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index db04b52..2b853ec 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -24,8 +24,6 @@ namespace teachos::arch::context_switching // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP // and triple fault. - // @MTO: SOMETIMES i get past a breakpoint here???? seems to happen when i actually pause before (f.e. inside the - // idt). NEVER happened when stepping through quickly. Can you reproduce this? kernel::cpu::set_interrupt_flag(); descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp index 34a10f1..e31e021 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp @@ -12,4 +12,6 @@ namespace teachos::arch::context_switching::segment_descriptor_table { return (std::bitset<8U>{_flags} & other) == other; } + + auto access_byte::operator|=(std::bitset<8U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp index 9885bda..e444a24 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp @@ -15,4 +15,6 @@ namespace teachos::arch::context_switching::segment_descriptor_table } auto gdt_flags::get_limit() const -> std::bitset<4U> { return std::bitset<4U>{_limit_2}; } + + auto gdt_flags::operator|=(std::bitset<4U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp index 346db9e..a497632 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp @@ -11,28 +11,26 @@ namespace teachos::arch::context_switching::segment_descriptor_table { namespace { - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_byte access_level) -> segment_descriptor { - uint8_t access_level_bits = - access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT | *reinterpret_cast<uint8_t *>(&access_level); - uint8_t gdt_flags_bits = gdt_flags::GRANULARITY | gdt_flags::LONG_MODE; + uint64_t const base = 0x0; + std::bitset<20U> const limit{0xFFFFF}; + gdt_flags flags{gdt_flags::GRANULARITY, limit}; + + access_level |= access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT; if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) { - access_level_bits |= access_byte::CODE_SEGMENT | access_byte::READABLE; + flags |= gdt_flags::LONG_MODE; + access_level |= access_byte::CODE_SEGMENT | access_byte::READABLE; } else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) { - gdt_flags_bits |= gdt_flags::UPPER_BOUND; - access_level_bits |= access_byte::WRITABLE; + flags |= gdt_flags::UPPER_BOUND; + access_level |= access_byte::WRITABLE; } - uint64_t const base = 0x0; - std::bitset<20U> const limit{0xFFFFF}; - access_byte const access_byte{access_level_bits}; - gdt_flags const gdt_flags{gdt_flags_bits, limit}; - segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; + segment_descriptor const segment_descriptor{access_level, flags, base, limit}; return segment_descriptor; } @@ -46,28 +44,34 @@ namespace teachos::arch::context_switching::segment_descriptor_table TSS_LIMIT}; return tss_descriptor; } + + auto create_global_descriptor_table() -> global_descriptor_table + { + segment_descriptor const null_segment{0}; + segment_descriptor const kernel_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); + segment_descriptor const kernel_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); + segment_descriptor const user_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); + segment_descriptor const user_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); + + // Task State Segment needs to be kept alive + static auto tss = new task_state_segment(); + segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss); + + global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment, tss_descriptor}; + return global_descriptor_table; + } } // namespace auto get_or_create_global_descriptor_table() -> global_descriptor_table & { - segment_descriptor const null_segment{0}; - segment_descriptor const kernel_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor const kernel_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor const user_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); - segment_descriptor const user_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); - - // Task State Segment needs to be kept alive - static auto tss = new task_state_segment(); - segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss); - // Global Descriptor Table needs to be kept alive - static global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment, tss_descriptor}; - return global_descriptor_table; + static global_descriptor_table gdt = create_global_descriptor_table(); + return gdt; } auto update_global_descriptor_table_register() -> void |
