diff options
Diffstat (limited to 'arch/x86_64/src/context_switching')
5 files changed, 69 insertions, 39 deletions
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 new file mode 100644 index 0000000..ee91e53 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp @@ -0,0 +1,5 @@ +#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/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp index dccce6b..639b079 100644 --- 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 @@ -38,8 +38,8 @@ namespace teachos::arch::context_switching::descriptor_table 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 code_segment{access_byte, gdt_flags, base, limit}; - return code_segment; + segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; + return segment_descriptor; } auto create_global_descriptor_table() -> global_descriptor_table @@ -53,6 +53,7 @@ namespace teachos::arch::context_switching::descriptor_table 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); @@ -85,44 +86,7 @@ namespace teachos::arch::context_switching::descriptor_table gdt_pointer == stored_gdt_pointer, "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); - // Calculate the offset of the gdt in bytes to the TSS descriptor - 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."); return gdt; } - auto reload_cs_register(uint16_t gdt_data_offset) -> void - { - asm volatile("mov %[input], %%ax\n" - "mov %%ax %%ds\n" // Data Segment - "mov %%ax %%es\n" // Extra Segment (used for string operations) - "mov %%ax %%fs\n" // General-purpose Segment - "mov %%ax %%gs\n" // General-purpose Segment - "mov %%ax %%ss\n" // Stack Segment - : /* no output from call */ - : [input] "r"(gdt_data_offset) - : "ax"); - } - - auto reload_segment_register(uint16_t gdt_code_offset, uint16_t gdt_data_offset) -> void - { - /* - Whatever you do with the GDT has no effect on the CPU until you load new Segment Selectors into Segment Registers. - For most of these registers, the process is as simple as using MOV instructions, but changing the CS register - requires code resembling a jump or call to elsewhere, as this is the only way its value is meant to be changed. - */ - auto function = [gdt_data_offset] { reload_cs_register(gdt_data_offset); }; - - asm volatile("push %[input]\n" - "lea %[func], %%rax\n" - "push %%rax\n" - "retfq\n" - : /* no output from call */ - : [input] "r"(gdt_code_offset), [func] "r"(&function) - : "rax"); - } } // 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 new file mode 100644 index 0000000..4d8b3e3 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/initialization.cpp @@ -0,0 +1,38 @@ +#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 new file mode 100644 index 0000000..9878664 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp @@ -0,0 +1,10 @@ +#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 new file mode 100644 index 0000000..b45324d --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp @@ -0,0 +1,13 @@ +#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 |
