aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/context_switching
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2025-03-28 18:35:28 +0100
committerFelix Morgner <felix.morgner@gmail.com>2025-03-28 18:39:15 +0100
commitfbd1ebe4f7c5985554fdca7c7fc05de15d47dd3a (patch)
treeaa693a6f6edc717a1f3e184141d0ee1c150c57d7 /arch/x86_64/src/context_switching
parent91c37142dbed40e42fd1a27a2755a79b8ccc329c (diff)
downloadteachos-fbd1ebe4f7c5985554fdca7c7fc05de15d47dd3a.tar.xz
teachos-fbd1ebe4f7c5985554fdca7c7fc05de15d47dd3a.zip
gdt: fix reload of GDT
The core problems were/are the following: - The flags of the segments were not entirely correct. Please recheck them against the spec! - The GDT pointer did not contain the address of the first (null) GTD entry, but the address of the stl::vector containing the GDT entries. - The far pointer must consist of: - the address to jump to - the byte index into the GDT for the desired segement descriptor to be loaded into CS. - The type of the "dummy" function we jump to was wrong (it's a function, we should declare it as such). - We cannot enable interrupts right now, since we die with a triple fault. This is caused by some initia fault which seems to lead to a general protection fault, which then triple faults since we cannot find the IDT. Some FIXMEs have been added to the code. Please look at them carefully and compare things against the specs.
Diffstat (limited to 'arch/x86_64/src/context_switching')
-rw-r--r--arch/x86_64/src/context_switching/main.cpp25
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp8
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp2
3 files changed, 18 insertions, 17 deletions
diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp
index 5d19f23..a5bd3fb 100644
--- a/arch/x86_64/src/context_switching/main.cpp
+++ b/arch/x86_64/src/context_switching/main.cpp
@@ -13,22 +13,21 @@ namespace teachos::arch::context_switching
decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table();
decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table();
- interrupt_descriptor_table::segment_selector segment_selector{
- 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL};
- kernel::cpu::far_pointer pointer{boot::reload_segment_register, segment_selector};
- kernel::cpu::jmp(pointer);
+ kernel::cpu::far_pointer pointer{&boot::reload_segment_register, 1 * sizeof(segment_descriptor_table::segment_descriptor)};
+ asm volatile("rex64 lcall *%[far_function_pointer]" : : [far_function_pointer] "m" (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);
+ // // 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.");
+ // 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();
+ // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP. Maybe because no IDT is loaded? Maybe our boot code segment is not set up correctly?
+ // kernel::cpu::set_interrupt_flag();
descriptor_tables tables = {global_descriptor_table, interrupt_descriptor_table};
return tables;
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 e6a489c..37ee778 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
@@ -20,12 +20,14 @@ namespace teachos::arch::context_switching::segment_descriptor_table
uint8_t gdt_flags_bits = gdt_flags::GRANULARITY;
if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT)
{
- gdt_flags_bits |= gdt_flags::LENGTH;
+ gdt_flags_bits |= gdt_flags::LONG_MODE;
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;
+ gdt_flags_bits |= 1 << 2;
+ // FIXME: Look at those bit flags, something seems off.
+ // gdt_flags_bits |= gdt_flags::UPPER_BOUND;
access_level_bits |= access_byte::WRITABLE;
}
@@ -78,7 +80,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table
// Calculate the size of the gdt in bytes - 1. This subtraction occurs because the maximum value of Size is 65535,
// while the GDT can be up to 65536 bytes in length (8192 entries). Further, no GDT can have a size of 0 bytes.
global_descriptor_table_pointer gdt_pointer{static_cast<uint16_t>((gdt.size() * sizeof(segment_descriptor)) - 1),
- &gdt};
+ gdt.data()};
kernel::cpu::load_global_descriptor_table(gdt_pointer);
auto const stored_gdt_pointer = kernel::cpu::store_global_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
index 132565f..a4a5de8 100644
--- 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
@@ -3,7 +3,7 @@
namespace teachos::arch::context_switching::segment_descriptor_table
{
global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length,
- global_descriptor_table * address)
+ segment_descriptor * address)
: table_length(table_length)
, address(address)
{