diff options
Diffstat (limited to 'arch/x86_64/src/context_switching')
8 files changed, 139 insertions, 67 deletions
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 index 4f18197..28f289c 100644 --- 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 @@ -2,4 +2,23 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { + gate_descriptor::gate_descriptor(uint128_t flags) + : _offset_1(flags) + , _selector(flags >> 19U, flags >> 16U) + , _ist(flags >> 32U) + , _flags(flags >> 40U) + , _offset_2(flags >> 48U) + { + // Nothing to do. + } + + gate_descriptor::gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset) + : _offset_1(offset) + , _selector(selector) + , _ist(ist) + , _flags(flags) + , _offset_2(offset >> 16U) + { + // Nothing to do. + } } // namespace teachos::arch::context_switching::interrupt_descriptor_table 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 new file mode 100644 index 0000000..e7379ef --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp @@ -0,0 +1,15 @@ +#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + idt_flags::idt_flags(uint8_t flags) + : _flags(flags) + { + // Nothing to do. + } + + auto idt_flags::contains_flags(std::bitset<8U> other) const -> bool + { + return (std::bitset<8U>{_flags} & other) == other; + } +} // 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 619a695..7346248 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 @@ -1,10 +1,28 @@ #include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/kernel/cpu/idtr.hpp" + namespace teachos::arch::context_switching::interrupt_descriptor_table { - auto initialize_interrupt_descriptor_table() -> void + namespace { - // DO NOT - } + auto create_interrupt_descriptor_table() -> interrupt_descriptor_table { return interrupt_descriptor_table{}; } + } // namespace + + auto initialize_interrupt_descriptor_table() -> interrupt_descriptor_table & + { + // Interrupt Descriptor Table needs to be kept alive + static auto idt = create_interrupt_descriptor_table(); + interrupt_descriptor_table_pointer idt_pointer{static_cast<uint16_t>(idt.size() - 1), &idt}; + kernel::cpu::load_interrupt_descriptor_table(idt_pointer); + + auto const stored_gdt_pointer = kernel::cpu::store_interrupt_descriptor_table(); + arch::exception_handling::assert( + idt_pointer == stored_gdt_pointer, + "[Interrupt Descriptor Table] Loaded IDTR value is not the same as the stored value."); + + return idt; + } } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp new file mode 100644 index 0000000..a70e75d --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp @@ -0,0 +1,10 @@ +#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + ist_offset::ist_offset(uint8_t index) + : _ist(index) + { + // Nothing to do. + } +} // namespace teachos::arch::context_switching::interrupt_descriptor_table 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 new file mode 100644 index 0000000..494e50f --- /dev/null +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp @@ -0,0 +1,16 @@ +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + segment_selector::segment_selector(uint16_t index, uint8_t flags) + : _flags(flags) + , _index(index) + { + // Nothing to do. + } + + auto segment_selector::contains_flags(std::bitset<3U> other) const -> bool + { + return (std::bitset<3U>{_flags} & other) == other; + } +} // 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 b682e79..95a25e0 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -11,10 +11,7 @@ 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(); + decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table(); kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer); @@ -30,7 +27,7 @@ namespace teachos::arch::context_switching kernel::cpu::set_interrupt_flag(); - descriptor_tables tables = {global_descriptor_table, idt}; + descriptor_tables tables = {global_descriptor_table, interrupt_descriptor_table}; return tables; } } // namespace teachos::arch::context_switching 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 1bbd24f..69cce19 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 @@ -9,69 +9,66 @@ namespace teachos::arch::context_switching::segment_descriptor_table { - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) - -> segment_descriptor + namespace { - 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) + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_byte access_level) + -> segment_descriptor { - gdt_flags_bitset |= gdt_flags::LENGTH; - access_level_bitset |= access_byte::CODE_SEGMENT | access_byte::READABLE; + 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; + if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) + { + gdt_flags_bits |= gdt_flags::LENGTH; + access_level_bits |= 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; + } + + 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}; + return segment_descriptor; } - else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) + + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor { - gdt_flags_bitset |= gdt_flags::UPPER_BOUND; - access_level_bitset |= access_byte::WRITABLE; + constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; + access_byte const tss_access_byte{access_byte::PRESENT | access_byte::DESCRIPTOR_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<uint64_t>(tss), + TSS_LIMIT}; + return tss_descriptor; } - 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); + 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); - 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; - } + // 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); - 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<uint64_t>(tss), TSS_LIMIT}; - return tss_descriptor; - } + 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; + } + } // namespace auto initialize_global_descriptor_table() -> global_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 index 6d831a1..74f93b2 100644 --- 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 @@ -3,11 +3,11 @@ 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) + : _limit_1(flags) + , _base_1(flags >> 16U) + , _access(flags >> 40U) + , _flag(flags >> 52U, flags >> 48U) + , _base_2(flags >> 56U) { // Nothing to do. } |
