aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/context_switching
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/context_switching')
-rw-r--r--arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp27
1 files changed, 12 insertions, 15 deletions
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 77bd3e9..21a76e8 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
@@ -54,9 +54,12 @@ namespace teachos::arch::context_switching::descriptor_table
create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER);
segment_descriptor 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 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};
+ 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;
}
@@ -67,20 +70,15 @@ namespace teachos::arch::context_switching::descriptor_table
access_byte::TASK_STATE_SEGMENT_AVAILABLE};
gdt_flags tss_gdt_flags{0U, limit};
uint64_t tss_address = reinterpret_cast<uint64_t>(tss);
- constexpr uint64_t tss_limit = sizeof(task_state_segment) - 1;
- segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, tss_limit};
-
+ constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1;
+ segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, TSS_LIMIT};
return tss_descriptor;
}
- auto initialize_global_descriptor_table() -> global_descriptor_table
+ auto initialize_global_descriptor_table() -> global_descriptor_table &
{
- auto gdt = create_global_descriptor_table();
-
- // Add TSS segment descriptor to GDT
- auto tss = new task_state_segment();
- auto tss_descriptor = create_task_state_segment_descriptor(tss);
- gdt.push_back(tss_descriptor);
+ // Global Descriptor Table needs to be kept alive
+ static auto gdt = create_global_descriptor_table();
// Load GDT into GDTR
global_descriptor_table_pointer gdt_pointer{static_cast<uint16_t>(gdt.size() - 1), &gdt};
@@ -91,14 +89,13 @@ 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.");
- // Load Task Register (LTR) using the index of TSS descriptor
- uint16_t tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor);
+ // 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 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;
}
} // namespace teachos::arch::context_switching::descriptor_table