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 --- .../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 ++++++++ 18 files changed, 236 insertions(+), 238 deletions(-) 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/x86_64/src/context_switching') 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 deleted file mode 100644 index 6b54451..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "arch/context_switching/descriptor_table/access_byte.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - access_byte::access_byte(uint8_t flags) - : _flags(flags) - { - // Nothing to do. - } - - auto access_byte::contains_flags(std::bitset<8U> other) const -> bool - { - return (std::bitset<8U>{_flags} & other) == other; - } -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp b/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp deleted file mode 100644 index ee91e53..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "arch/context_switching/descriptor_table/gate_descriptor.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ -} // namespace teachos::arch::context_switching::descriptor_table 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 deleted file mode 100644 index 9e95182..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "arch/context_switching/descriptor_table/gdt_flags.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - gdt_flags::gdt_flags(uint8_t flags, std::bitset<20U> limit) - : _limit_2(limit.to_ulong() >> 16U) - , _flags(flags) - { - // Nothing to do. - } - - auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool - { - return (std::bitset<4U>{_flags} & other) == other; - } - - auto descriptor_table::gdt_flags::get_limit() const -> std::bitset<4U> { return std::bitset<4U>{_limit_2}; } -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp deleted file mode 100644 index 639b079..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" - -#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" -#include "arch/context_switching/descriptor_table/task_state_segment.hpp" -#include "arch/exception_handling/assert.hpp" -#include "arch/kernel/cpu/gdtr.hpp" -#include "arch/kernel/cpu/tr.hpp" -#include "arch/stl/vector.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) - -> segment_descriptor - { - uint8_t access_level_bitset = access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT; - if (access_level == access_level::KERNEL) - { - access_level_bitset |= access_byte::ACCESS_LEVEL_KERNEL; - } - else if (access_level == access_level::USER) - { - access_level_bitset |= access_byte::ACCESS_LEVEL_USER; - } - - uint8_t gdt_flags_bitset = gdt_flags::GRANULARITY; - if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) - { - gdt_flags_bitset |= gdt_flags::LENGTH; - access_level_bitset |= access_byte::CODE_SEGMENT | access_byte::READABLE; - } - else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) - { - gdt_flags_bitset |= gdt_flags::UPPER_BOUND; - access_level_bitset |= access_byte::WRITABLE; - } - - uint64_t const base = 0x0; - std::bitset<20U> const limit{0xFFFFF}; - access_byte const access_byte{access_level_bitset}; - gdt_flags const gdt_flags{gdt_flags_bitset, limit}; - segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; - return segment_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_level::KERNEL); - segment_descriptor const kernel_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::KERNEL); - segment_descriptor const user_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); - segment_descriptor const user_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_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 const global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment, tss_descriptor}; - return global_descriptor_table; - } - - auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor - { - constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; - access_byte const tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | - access_byte::TASK_STATE_SEGMENT_AVAILABLE}; - gdt_flags const tss_gdt_flags{0U, TSS_LIMIT}; - segment_descriptor const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast(tss), TSS_LIMIT}; - return tss_descriptor; - } - - auto initialize_global_descriptor_table() -> global_descriptor_table & - { - // Global Descriptor Table needs to be kept alive - static auto gdt = create_global_descriptor_table(); - - global_descriptor_table_pointer gdt_pointer{static_cast(gdt.size() - 1), &gdt}; - kernel::cpu::load_global_descriptor_table(gdt_pointer); - - auto const stored_gdt_pointer = kernel::cpu::store_global_descriptor_table(); - arch::exception_handling::assert( - gdt_pointer == stored_gdt_pointer, - "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); - - return gdt; - } - -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp deleted file mode 100644 index f552496..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length, - global_descriptor_table * address) - : table_length(table_length) - , address(address) - { - // Nothing to do. - } -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/initialization.cpp b/arch/x86_64/src/context_switching/descriptor_table/initialization.cpp deleted file mode 100644 index 4d8b3e3..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/initialization.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "arch/context_switching/descriptor_table/initialization.hpp" - -#include "arch/boot/pointers.hpp" -#include "arch/exception_handling/assert.hpp" -#include "arch/kernel/cpu/if.hpp" -#include "arch/kernel/cpu/jmp.hpp" -#include "arch/kernel/cpu/tr.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - auto initialize_descriptor_tables() -> descriptor_tables - { - decltype(auto) global_descriptor_table = context_switching::descriptor_table::initialize_global_descriptor_table(); - - // TODO: Replace random construction with return value of initialization. - interrupt_descriptor_table idt{}; - context_switching::descriptor_table::initialize_interrupt_descriptor_table(); - - kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer); - - uint16_t const tss_selector = (global_descriptor_table.size() - 1) << 3; - kernel::cpu::load_task_register(tss_selector); - - // Not sure if offset index or offset in bytes is needed! - // uint16_t const tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor); - // kernel::cpu::load_task_register(tss_selector); - - auto const stored_task_register = kernel::cpu::store_task_register(); - arch::exception_handling::assert(tss_selector == stored_task_register, - "[Global Descriptor Table] Loaded TR value is not the same as the stored value."); - - kernel::cpu::set_interrupt_flag(); - - descriptor_tables descriptor_tables = {global_descriptor_table, idt}; - return descriptor_tables; - } - -} // namespace teachos::arch::context_switching::descriptor_table \ No newline at end of file diff --git a/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp b/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp deleted file mode 100644 index 9878664..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - auto initialize_interrupt_descriptor_table() -> void - { - // DO NOT - } - -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp b/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp deleted file mode 100644 index b45324d..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - interrupt_descriptor_table_pointer::interrupt_descriptor_table_pointer(uint16_t table_length, - interrupt_descriptor_table * address) - : table_length(table_length) - , address(address) - { - // Nothing to do. - } - -} // namespace teachos::arch::context_switching::descriptor_table 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 deleted file mode 100644 index 2385c58..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - segment_descriptor::segment_descriptor(uint128_t flags) - : _limit_1(flags << 112U) - , _base_1((flags >> 16U) << 88U) - , _access((flags >> 40U) << 80U) - , _flag((flags >> 52U) << 72U, (flags >> 48U) << 72U) - , _base_2((flags >> 56U) << 32U) - { - // Nothing to do. - } - - segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, - std::bitset<20U> limit) - : _limit_1(limit.to_ulong()) - , _base_1(base) - , _access(access_byte) - , _flag(flags) - , _base_2(base >> 24U) - { - // 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.contains_flags(access_byte::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT - : segment_descriptor_type::DATA_SEGMENT; - } -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp new file mode 100644 index 0000000..4f18197 --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp @@ -0,0 +1,5 @@ +#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ +} // 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 new file mode 100644 index 0000000..619a695 --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp @@ -0,0 +1,10 @@ +#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + auto initialize_interrupt_descriptor_table() -> void + { + // DO NOT + } + +} // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp new file mode 100644 index 0000000..981944d --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp @@ -0,0 +1,13 @@ +#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + interrupt_descriptor_table_pointer::interrupt_descriptor_table_pointer(uint16_t table_length, + interrupt_descriptor_table * address) + : table_length(table_length) + , address(address) + { + // Nothing to do. + } + +} // 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 new file mode 100644 index 0000000..b682e79 --- /dev/null +++ b/arch/x86_64/src/context_switching/main.cpp @@ -0,0 +1,36 @@ +#include "arch/context_switching/main.hpp" + +#include "arch/boot/pointers.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/kernel/cpu/if.hpp" +#include "arch/kernel/cpu/jmp.hpp" +#include "arch/kernel/cpu/tr.hpp" + +namespace teachos::arch::context_switching +{ + auto initialize_descriptor_tables() -> descriptor_tables + { + decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table(); + + // TODO: Replace random construction with return value of initialization. + interrupt_descriptor_table::interrupt_descriptor_table idt{}; + interrupt_descriptor_table::initialize_interrupt_descriptor_table(); + + kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer); + + // Load task state segment descriptor from the last element in the global descriptor table, done by calculating + // offset in bytes to the start of the segment descriptor (5 * 16) = 80 + uint16_t const tss_selector = + (global_descriptor_table.size() - 1) * sizeof(segment_descriptor_table::segment_descriptor); + kernel::cpu::load_task_register(tss_selector); + + auto const stored_task_register = kernel::cpu::store_task_register(); + arch::exception_handling::assert(tss_selector == stored_task_register, + "[Global Descriptor Table] Loaded TR value is not the same as the stored value."); + + kernel::cpu::set_interrupt_flag(); + + descriptor_tables tables = {global_descriptor_table, idt}; + return tables; + } +} // namespace teachos::arch::context_switching 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 new file mode 100644 index 0000000..34a10f1 --- /dev/null +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp @@ -0,0 +1,15 @@ +#include "arch/context_switching/segment_descriptor_table/access_byte.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + access_byte::access_byte(uint8_t flags) + : _flags(flags) + { + // Nothing to do. + } + + auto access_byte::contains_flags(std::bitset<8U> other) const -> bool + { + return (std::bitset<8U>{_flags} & other) == other; + } +} // 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 new file mode 100644 index 0000000..9885bda --- /dev/null +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp @@ -0,0 +1,18 @@ +#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + gdt_flags::gdt_flags(uint8_t flags, std::bitset<20U> limit) + : _limit_2(limit.to_ulong() >> 16U) + , _flags(flags) + { + // Nothing to do. + } + + auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool + { + return (std::bitset<4U>{_flags} & other) == other; + } + + auto gdt_flags::get_limit() const -> std::bitset<4U> { return std::bitset<4U>{_limit_2}; } +} // 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 new file mode 100644 index 0000000..1bbd24f --- /dev/null +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp @@ -0,0 +1,92 @@ +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp" + +#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" +#include "arch/context_switching/segment_descriptor_table/task_state_segment.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/kernel/cpu/gdtr.hpp" +#include "arch/kernel/cpu/tr.hpp" +#include "arch/stl/vector.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) + -> segment_descriptor + { + uint8_t access_level_bitset = access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT; + if (access_level == access_level::KERNEL) + { + access_level_bitset |= access_byte::ACCESS_LEVEL_KERNEL; + } + else if (access_level == access_level::USER) + { + access_level_bitset |= access_byte::ACCESS_LEVEL_USER; + } + + uint8_t gdt_flags_bitset = gdt_flags::GRANULARITY; + if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) + { + gdt_flags_bitset |= gdt_flags::LENGTH; + access_level_bitset |= access_byte::CODE_SEGMENT | access_byte::READABLE; + } + else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) + { + gdt_flags_bitset |= gdt_flags::UPPER_BOUND; + access_level_bitset |= access_byte::WRITABLE; + } + + uint64_t const base = 0x0; + std::bitset<20U> const limit{0xFFFFF}; + access_byte const access_byte{access_level_bitset}; + gdt_flags const gdt_flags{gdt_flags_bitset, limit}; + segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; + return segment_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_level::KERNEL); + segment_descriptor const kernel_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::KERNEL); + segment_descriptor const user_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); + segment_descriptor const user_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_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 const global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment, tss_descriptor}; + return global_descriptor_table; + } + + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor + { + constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; + access_byte const tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | + access_byte::TASK_STATE_SEGMENT_AVAILABLE}; + gdt_flags const tss_gdt_flags{0U, TSS_LIMIT}; + segment_descriptor const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast(tss), TSS_LIMIT}; + return tss_descriptor; + } + + auto initialize_global_descriptor_table() -> global_descriptor_table & + { + // Global Descriptor Table needs to be kept alive + static auto gdt = create_global_descriptor_table(); + + global_descriptor_table_pointer gdt_pointer{static_cast(gdt.size() - 1), &gdt}; + kernel::cpu::load_global_descriptor_table(gdt_pointer); + + auto const stored_gdt_pointer = kernel::cpu::store_global_descriptor_table(); + arch::exception_handling::assert( + gdt_pointer == stored_gdt_pointer, + "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); + + return gdt; + } + +} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp new file mode 100644 index 0000000..132565f --- /dev/null +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp @@ -0,0 +1,12 @@ +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length, + global_descriptor_table * address) + : table_length(table_length) + , address(address) + { + // Nothing to do. + } +} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp new file mode 100644 index 0000000..6d831a1 --- /dev/null +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp @@ -0,0 +1,35 @@ +#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + segment_descriptor::segment_descriptor(uint128_t flags) + : _limit_1(flags << 112U) + , _base_1((flags >> 16U) << 88U) + , _access((flags >> 40U) << 80U) + , _flag((flags >> 52U) << 72U, (flags >> 48U) << 72U) + , _base_2((flags >> 56U) << 32U) + { + // Nothing to do. + } + + segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, + std::bitset<20U> limit) + : _limit_1(limit.to_ulong()) + , _base_1(base) + , _access(access_byte) + , _flag(flags) + , _base_2(base >> 24U) + { + // 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.contains_flags(access_byte::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT + : segment_descriptor_type::DATA_SEGMENT; + } +} // namespace teachos::arch::context_switching::segment_descriptor_table -- cgit v1.2.3