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 --- arch/x86_64/src/context_switching/main.cpp | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 arch/x86_64/src/context_switching/main.cpp (limited to 'arch/x86_64/src/context_switching/main.cpp') 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 -- cgit v1.2.3 From 66fefaeb16bcbc4eae5ce5256ae76f51a155cded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 25 Mar 2025 16:58:24 +0000 Subject: Implement idtr structure and document possible flags. --- arch/x86_64/src/context_switching/main.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') 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 -- cgit v1.2.3 From a6c5f6a273d0c5c4161f600fca6d4fe49858c23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 27 Mar 2025 09:40:32 +0000 Subject: Attempt to fix crash in far jump. WIP does not return from call to assembler method --- arch/x86_64/src/context_switching/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 95a25e0..c3c0cf0 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -13,7 +13,10 @@ 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(); - kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer); + interrupt_descriptor_table::segment_selector segment_selector{ + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + kernel::cpu::far_pointer pointer{boot::segment_register_reload_pointer, segment_selector}; + kernel::cpu::jmp(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 -- cgit v1.2.3 From 9ddfcd02413a93718e8cde53f9ba5a96a5b29b8f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Mar 2025 14:02:05 +0000 Subject: update long jump handling --- arch/x86_64/src/context_switching/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index c3c0cf0..1417a25 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -13,10 +13,8 @@ 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::segment_register_reload_pointer, segment_selector}; - kernel::cpu::jmp(pointer); + // Execute trampoline function for the GDT loading long jump + boot::reload_segment_register_trampoline(); // 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 -- cgit v1.2.3 From e0eae9b9e905a1842b333823bfdb7c253cda8d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 28 Mar 2025 09:59:09 +0000 Subject: Revert "update long jump handling" This reverts commit 9ddfcd02413a93718e8cde53f9ba5a96a5b29b8f. --- arch/x86_64/src/context_switching/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 1417a25..c3c0cf0 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -13,8 +13,10 @@ 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(); - // Execute trampoline function for the GDT loading long jump - boot::reload_segment_register_trampoline(); + interrupt_descriptor_table::segment_selector segment_selector{ + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + kernel::cpu::far_pointer pointer{boot::segment_register_reload_pointer, segment_selector}; + kernel::cpu::jmp(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 -- cgit v1.2.3 From 437c3554f9a86b6347d97f5e2a82543c1e068b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 28 Mar 2025 10:52:25 +0000 Subject: Attempt to fix ljmp. Might not be possible in Long mode --- arch/x86_64/src/context_switching/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index c3c0cf0..5d19f23 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -15,7 +15,7 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::segment_selector segment_selector{ 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; - kernel::cpu::far_pointer pointer{boot::segment_register_reload_pointer, segment_selector}; + kernel::cpu::far_pointer pointer{boot::reload_segment_register, segment_selector}; kernel::cpu::jmp(pointer); // Load task state segment descriptor from the last element in the global descriptor table, done by calculating -- cgit v1.2.3 From fbd1ebe4f7c5985554fdca7c7fc05de15d47dd3a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 28 Mar 2025 18:35:28 +0100 Subject: 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. --- arch/x86_64/src/context_switching/main.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') 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; -- cgit v1.2.3 From aba154ad01fc0e1e1274f2582b1493e78daa2559 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 29 Mar 2025 14:47:04 +0000 Subject: fix gdt segments, improve idt and trial&error for triple fault --- arch/x86_64/src/context_switching/main.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index a5bd3fb..f449a3a 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -10,24 +10,30 @@ namespace teachos::arch::context_switching { auto initialize_descriptor_tables() -> descriptor_tables { + kernel::cpu::clear_interrupt_flag(); decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table(); decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table(); - 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)); + 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."); - // 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(); + // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP + // and triple fault. + + // @MTO: SOMETIMES i get past a breakpoint here???? seems to happen when i actually pause before (f.e. inside the + // idt). NEVER happened when stepping through quickly. Can you reproduce this? + kernel::cpu::set_interrupt_flag(); descriptor_tables tables = {global_descriptor_table, interrupt_descriptor_table}; return tables; -- cgit v1.2.3 From 8d16dcb672c4b5f4b0a12ef2eac3486f1b2bb316 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 29 Mar 2025 14:47:23 +0000 Subject: remove empty line --- arch/x86_64/src/context_switching/main.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index f449a3a..008da2f 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -30,7 +30,6 @@ namespace teachos::arch::context_switching // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP // and triple fault. - // @MTO: SOMETIMES i get past a breakpoint here???? seems to happen when i actually pause before (f.e. inside the // idt). NEVER happened when stepping through quickly. Can you reproduce this? kernel::cpu::set_interrupt_flag(); -- cgit v1.2.3 From abe7bd7480c8f4e1e30b9f0f3b98966222817f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 31 Mar 2025 10:38:53 +0000 Subject: Clean up global descriptor table initalization --- arch/x86_64/src/context_switching/main.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 008da2f..db04b52 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -11,22 +11,16 @@ namespace teachos::arch::context_switching auto initialize_descriptor_tables() -> descriptor_tables { kernel::cpu::clear_interrupt_flag(); - decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table(); - decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table(); - 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)); + segment_descriptor_table::update_global_descriptor_table_register(); + interrupt_descriptor_table::update_interrupt_descriptor_table_register(); - // 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); + interrupt_descriptor_table::segment_selector segment_selector{ + 2U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + kernel::cpu::far_pointer pointer{&boot::reload_segment_register, segment_selector}; + kernel::cpu::jmp(pointer); - 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."); + segment_descriptor_table::update_task_state_segment_register(); // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP // and triple fault. @@ -34,7 +28,8 @@ namespace teachos::arch::context_switching // idt). NEVER happened when stepping through quickly. Can you reproduce this? kernel::cpu::set_interrupt_flag(); - descriptor_tables tables = {global_descriptor_table, interrupt_descriptor_table}; + descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), + interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; return tables; } } // namespace teachos::arch::context_switching -- cgit v1.2.3 From e8fb1d771d9aa4d1cb5b18cd0483c7e5731aeecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 31 Mar 2025 13:18:56 +0000 Subject: Improve create_segment readability --- arch/x86_64/src/context_switching/main.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index db04b52..2b853ec 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -24,8 +24,6 @@ namespace teachos::arch::context_switching // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP // and triple fault. - // @MTO: SOMETIMES i get past a breakpoint here???? seems to happen when i actually pause before (f.e. inside the - // idt). NEVER happened when stepping through quickly. Can you reproduce this? kernel::cpu::set_interrupt_flag(); descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), -- cgit v1.2.3 From fc4a2306b803ccfc27f1bdc4a831176a5278a9d5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Wed, 2 Apr 2025 09:57:54 +0000 Subject: fix interrupt handler and idt --- arch/x86_64/src/context_switching/main.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 2b853ec..ac53735 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -22,8 +22,6 @@ namespace teachos::arch::context_switching segment_descriptor_table::update_task_state_segment_register(); - // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP - // and triple fault. kernel::cpu::set_interrupt_flag(); descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), -- cgit v1.2.3 From 8b66e4cd1d1487fefbae459f556396db61497a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 4 Apr 2025 15:05:59 +0000 Subject: Multiplication by two for segment selector index --- arch/x86_64/src/context_switching/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index ac53735..6614065 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -16,7 +16,7 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::update_interrupt_descriptor_table_register(); interrupt_descriptor_table::segment_selector segment_selector{ - 2U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; kernel::cpu::far_pointer pointer{&boot::reload_segment_register, segment_selector}; kernel::cpu::jmp(pointer); -- cgit v1.2.3 From a8852f91967a7e55e62e30f5cc07d076092b8b78 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 5 Apr 2025 15:27:20 +0000 Subject: add wip context switch to user mode --- arch/x86_64/src/context_switching/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 6614065..124df93 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,9 +1,9 @@ #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/segment_register.hpp" #include "arch/kernel/cpu/tr.hpp" namespace teachos::arch::context_switching @@ -17,7 +17,7 @@ namespace teachos::arch::context_switching 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::far_pointer pointer{&kernel::cpu::reload_segment_registers, segment_selector}; kernel::cpu::jmp(pointer); segment_descriptor_table::update_task_state_segment_register(); -- cgit v1.2.3 From 8a23a47425162894141f4eac488fb1f1bb3f7dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 7 Apr 2025 15:42:38 +0000 Subject: Fix naming from jmp to call for Far Call --- arch/x86_64/src/context_switching/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 124df93..762445f 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,8 +1,8 @@ #include "arch/context_switching/main.hpp" #include "arch/exception_handling/assert.hpp" +#include "arch/kernel/cpu/call.hpp" #include "arch/kernel/cpu/if.hpp" -#include "arch/kernel/cpu/jmp.hpp" #include "arch/kernel/cpu/segment_register.hpp" #include "arch/kernel/cpu/tr.hpp" @@ -18,7 +18,7 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::segment_selector segment_selector{ 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; kernel::cpu::far_pointer pointer{&kernel::cpu::reload_segment_registers, segment_selector}; - kernel::cpu::jmp(pointer); + kernel::cpu::call(pointer); segment_descriptor_table::update_task_state_segment_register(); -- cgit v1.2.3 From dff78de795a89c181e9c94b26db2f16988e8f4d6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 10 Apr 2025 12:11:55 +0000 Subject: move context_switch function and environment into different directory --- arch/x86_64/src/context_switching/main.cpp | 72 ++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 762445f..3efba45 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -5,9 +5,59 @@ #include "arch/kernel/cpu/if.hpp" #include "arch/kernel/cpu/segment_register.hpp" #include "arch/kernel/cpu/tr.hpp" +#include "arch/video/vga/text.hpp" namespace teachos::arch::context_switching { + namespace + { + + /** + * @brief Switch context into the mode defined in the segment selectors. + * + * Setup the stack IRETQ expects to switch the mode: + * 1. push data selector + * 2. push current stack pointer + * 3. push eflags + * 4. push code segment selector + * 5. push return address + * + * @param data_segment + * @param code_segment + * @param address + */ + [[gnu::naked]] + auto far_return(context_switching::interrupt_descriptor_table::segment_selector data_segment, + context_switching::interrupt_descriptor_table::segment_selector code_segment, uint64_t address) + -> void + { + asm volatile("mov %[data_segment], %%rax\n" + "mov %%rax, %%ds\n" + "mov %%rax, %%es\n" + "mov %%rax, %%fs\n" + "mov %%rax, %%gs\n" + "mov %%rsp, %%rax\n" + + "push %[data_segment]\n" + "push %%rax\n" + "pushfq\n" + "push %[code_segment]\n" + "mov %[return_function], %%rax\n" + "push %%rax\n" + + "iretq\n" + : + : [data_segment] "m"(data_segment), [code_segment] "m"(code_segment), [return_function] "r"(address) + : "rax"); + } + + constexpr context_switching::interrupt_descriptor_table::segment_selector USER_CODE_SEGMENT_SELECTOR{ + 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER}; + constexpr context_switching::interrupt_descriptor_table::segment_selector USER_DATA_SEGMENT_SELECTOR{ + 4U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER}; + + } // namespace + auto initialize_descriptor_tables() -> descriptor_tables { kernel::cpu::clear_interrupt_flag(); @@ -28,4 +78,26 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; return tables; } + + auto user_mode_main() -> void + { + auto current_segment = kernel::cpu::read_code_segment_register(); + arch::exception_handling::assert(USER_CODE_SEGMENT_SELECTOR == current_segment, + "[Context Switching] Context switch into user mode not successful"); + + video::vga::text::write("User Mode!!!", video::vga::text::common_attributes::green_on_black); + } + + auto switch_to_user_mode() -> void + { + switch_context(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR, user_mode_main); + } + + auto switch_context(interrupt_descriptor_table::segment_selector data_segment, + interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void + { + kernel::cpu::set_segment_registers(data_segment); + far_return(data_segment, code_segment, reinterpret_cast(return_function)); + } + } // namespace teachos::arch::context_switching -- cgit v1.2.3 From 87091e2246d2c4c794d9d6a0c5398ca80d92335a Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 10 Apr 2025 12:29:19 +0000 Subject: add register validation and asserts --- arch/x86_64/src/context_switching/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 3efba45..0f2ec93 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -2,6 +2,7 @@ #include "arch/exception_handling/assert.hpp" #include "arch/kernel/cpu/call.hpp" +#include "arch/kernel/cpu/control_register.hpp" #include "arch/kernel/cpu/if.hpp" #include "arch/kernel/cpu/segment_register.hpp" #include "arch/kernel/cpu/tr.hpp" @@ -82,10 +83,12 @@ namespace teachos::arch::context_switching auto user_mode_main() -> void { auto current_segment = kernel::cpu::read_code_segment_register(); - arch::exception_handling::assert(USER_CODE_SEGMENT_SELECTOR == current_segment, - "[Context Switching] Context switch into user mode not successful"); + exception_handling::assert(USER_CODE_SEGMENT_SELECTOR == current_segment, + "[Context Switching] Context switch into user mode not successful"); + exception_handling::assert(USER_DATA_SEGMENT_SELECTOR == kernel::cpu::validate_data_segment_registers(), + "[Context Switching] Context switch into user mode not successful"); - video::vga::text::write("User Mode!!!", video::vga::text::common_attributes::green_on_black); + video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } auto switch_to_user_mode() -> void -- cgit v1.2.3 From 9a185c1533bd2197d0e830369b4cc26abf88e2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 11 Apr 2025 09:25:04 +0000 Subject: Document methods and move them into kernel cpu folder --- arch/x86_64/src/context_switching/main.cpp | 63 +++++++----------------------- 1 file changed, 14 insertions(+), 49 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 0f2ec93..5cac878 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -12,46 +12,6 @@ namespace teachos::arch::context_switching { namespace { - - /** - * @brief Switch context into the mode defined in the segment selectors. - * - * Setup the stack IRETQ expects to switch the mode: - * 1. push data selector - * 2. push current stack pointer - * 3. push eflags - * 4. push code segment selector - * 5. push return address - * - * @param data_segment - * @param code_segment - * @param address - */ - [[gnu::naked]] - auto far_return(context_switching::interrupt_descriptor_table::segment_selector data_segment, - context_switching::interrupt_descriptor_table::segment_selector code_segment, uint64_t address) - -> void - { - asm volatile("mov %[data_segment], %%rax\n" - "mov %%rax, %%ds\n" - "mov %%rax, %%es\n" - "mov %%rax, %%fs\n" - "mov %%rax, %%gs\n" - "mov %%rsp, %%rax\n" - - "push %[data_segment]\n" - "push %%rax\n" - "pushfq\n" - "push %[code_segment]\n" - "mov %[return_function], %%rax\n" - "push %%rax\n" - - "iretq\n" - : - : [data_segment] "m"(data_segment), [code_segment] "m"(code_segment), [return_function] "r"(address) - : "rax"); - } - constexpr context_switching::interrupt_descriptor_table::segment_selector USER_CODE_SEGMENT_SELECTOR{ 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER}; constexpr context_switching::interrupt_descriptor_table::segment_selector USER_DATA_SEGMENT_SELECTOR{ @@ -61,6 +21,14 @@ namespace teachos::arch::context_switching auto initialize_descriptor_tables() -> descriptor_tables { + static bool initalized = false; + if (initalized) + { + descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), + interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; + return tables; + } + kernel::cpu::clear_interrupt_flag(); segment_descriptor_table::update_global_descriptor_table_register(); @@ -68,7 +36,7 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::segment_selector segment_selector{ 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; - kernel::cpu::far_pointer pointer{&kernel::cpu::reload_segment_registers, segment_selector}; + kernel::cpu::far_pointer pointer{&kernel::cpu::reload_data_segment_registers, segment_selector}; kernel::cpu::call(pointer); segment_descriptor_table::update_task_state_segment_register(); @@ -77,17 +45,13 @@ namespace teachos::arch::context_switching descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; + initalized = true; return tables; } auto user_mode_main() -> void { - auto current_segment = kernel::cpu::read_code_segment_register(); - exception_handling::assert(USER_CODE_SEGMENT_SELECTOR == current_segment, - "[Context Switching] Context switch into user mode not successful"); - exception_handling::assert(USER_DATA_SEGMENT_SELECTOR == kernel::cpu::validate_data_segment_registers(), - "[Context Switching] Context switch into user mode not successful"); - + kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } @@ -99,8 +63,9 @@ namespace teachos::arch::context_switching auto switch_context(interrupt_descriptor_table::segment_selector data_segment, interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void { - kernel::cpu::set_segment_registers(data_segment); - far_return(data_segment, code_segment, reinterpret_cast(return_function)); + (void)initialize_descriptor_tables(); + kernel::cpu::set_data_segment_registers(data_segment); + kernel::cpu::set_code_segment_register(data_segment, code_segment, reinterpret_cast(return_function)); } } // namespace teachos::arch::context_switching -- cgit v1.2.3 From 0c75a6ef8e47106e7fc51ca5e11eb4116e879e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 11 Apr 2025 10:50:03 +0000 Subject: Improve initialize_descriptor_tables --- arch/x86_64/src/context_switching/main.cpp | 31 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 5cac878..952a3b2 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -12,6 +12,10 @@ namespace teachos::arch::context_switching { namespace { + constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{ + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + constexpr kernel::cpu::far_pointer KERNEL_CODE_POINTER{&kernel::cpu::reload_data_segment_registers, + KERNEL_CODE_SEGMENT_SELECTOR}; constexpr context_switching::interrupt_descriptor_table::segment_selector USER_CODE_SEGMENT_SELECTOR{ 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER}; constexpr context_switching::interrupt_descriptor_table::segment_selector USER_DATA_SEGMENT_SELECTOR{ @@ -22,30 +26,23 @@ namespace teachos::arch::context_switching auto initialize_descriptor_tables() -> descriptor_tables { static bool initalized = false; - if (initalized) - { - descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), - interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; - return tables; - } - - kernel::cpu::clear_interrupt_flag(); - segment_descriptor_table::update_global_descriptor_table_register(); - interrupt_descriptor_table::update_interrupt_descriptor_table_register(); + if (!initalized) + { + kernel::cpu::clear_interrupt_flag(); - interrupt_descriptor_table::segment_selector segment_selector{ - 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; - kernel::cpu::far_pointer pointer{&kernel::cpu::reload_data_segment_registers, segment_selector}; - kernel::cpu::call(pointer); + segment_descriptor_table::update_global_descriptor_table_register(); + interrupt_descriptor_table::update_interrupt_descriptor_table_register(); - segment_descriptor_table::update_task_state_segment_register(); + kernel::cpu::call(KERNEL_CODE_POINTER); + segment_descriptor_table::update_task_state_segment_register(); - kernel::cpu::set_interrupt_flag(); + kernel::cpu::set_interrupt_flag(); + initalized = true; + } descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()}; - initalized = true; return tables; } -- cgit v1.2.3 From eafe8533bb5ccbe15bd8ffbc917b38122b04a157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Apr 2025 15:21:52 +0000 Subject: Add stack frame allocator. Fix stl vector bug and create stl stack implementation --- arch/x86_64/src/context_switching/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 952a3b2..486a09f 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -21,6 +21,8 @@ namespace teachos::arch::context_switching constexpr context_switching::interrupt_descriptor_table::segment_selector USER_DATA_SEGMENT_SELECTOR{ 4U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER}; + auto reload_global_descriptor_table_register() -> void { kernel::cpu::call(KERNEL_CODE_POINTER); } + } // namespace auto initialize_descriptor_tables() -> descriptor_tables @@ -34,7 +36,7 @@ namespace teachos::arch::context_switching segment_descriptor_table::update_global_descriptor_table_register(); interrupt_descriptor_table::update_interrupt_descriptor_table_register(); - kernel::cpu::call(KERNEL_CODE_POINTER); + reload_global_descriptor_table_register(); segment_descriptor_table::update_task_state_segment_register(); kernel::cpu::set_interrupt_flag(); -- cgit v1.2.3 From 576a7a95b2462ec4938de9fe344657ca04b2ba34 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 17 Apr 2025 14:14:49 +0000 Subject: add syscall interrupt handler --- arch/x86_64/src/context_switching/main.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 952a3b2..fc8790f 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -49,6 +49,9 @@ namespace teachos::arch::context_switching auto user_mode_main() -> void { kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); + + asm volatile("INT $0x80"); + video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } -- cgit v1.2.3 From 0986058bb9ca5b4afd7c578c815dc3a4c08808a9 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Mon, 21 Apr 2025 08:18:41 +0000 Subject: WIP syscall --- arch/x86_64/src/context_switching/main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 7be286a..faaf831 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -52,7 +52,14 @@ namespace teachos::arch::context_switching { kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); - asm volatile("INT $0x80"); + // TODO/INFO: + // https://stackoverflow.com/questions/46022184/osdev-syscall-sysret-and-sysenter-sysexit-instructions-enabling + // https://stackoverflow.com/questions/12806584/what-is-better-int-0x80-or-syscall-in-32-bit-code-on-linux + // + // People claim that SYSENTER is for 32-Bit, while SYSCALL is for 64-Bit! + + // asm volatile("INT $0x80"); + asm volatile("SYSCALL"); video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } -- cgit v1.2.3 From c865eff02ae1978b4f665432d853374d1ffacecf Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 10:21:29 +0000 Subject: create trampoline for syscall --- arch/x86_64/src/context_switching/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index faaf831..c949488 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,5 +1,6 @@ #include "arch/context_switching/main.hpp" +#include "arch/boot/pointers.hpp" #include "arch/exception_handling/assert.hpp" #include "arch/kernel/cpu/call.hpp" #include "arch/kernel/cpu/control_register.hpp" @@ -59,7 +60,8 @@ namespace teachos::arch::context_switching // People claim that SYSENTER is for 32-Bit, while SYSCALL is for 64-Bit! // asm volatile("INT $0x80"); - asm volatile("SYSCALL"); + // asm volatile("SYSCALL"); + boot::syscall_trampoline(); video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } -- cgit v1.2.3 From 7261c64bb236a313ed8846a9c9dbded6890a9e98 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 11:20:02 +0000 Subject: wip implement syscall in cpp --- arch/x86_64/src/context_switching/main.cpp | 43 +++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index c949488..85cefe5 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,6 +1,7 @@ #include "arch/context_switching/main.hpp" #include "arch/boot/pointers.hpp" +#include "arch/context_switching/syscall_handler.hpp" #include "arch/exception_handling/assert.hpp" #include "arch/kernel/cpu/call.hpp" #include "arch/kernel/cpu/control_register.hpp" @@ -53,15 +54,7 @@ namespace teachos::arch::context_switching { kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); - // TODO/INFO: - // https://stackoverflow.com/questions/46022184/osdev-syscall-sysret-and-sysenter-sysexit-instructions-enabling - // https://stackoverflow.com/questions/12806584/what-is-better-int-0x80-or-syscall-in-32-bit-code-on-linux - // - // People claim that SYSENTER is for 32-Bit, while SYSCALL is for 64-Bit! - - // asm volatile("INT $0x80"); - // asm volatile("SYSCALL"); - boot::syscall_trampoline(); + asm volatile("SYSCALL"); video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); } @@ -79,4 +72,36 @@ namespace teachos::arch::context_switching kernel::cpu::set_code_segment_register(data_segment, code_segment, reinterpret_cast(return_function)); } + auto setup_syscall() -> void + { + uint64_t handler = reinterpret_cast(syscall_handler); + asm volatile( + /* Write syscall_handler pointer in IA32_LSTAR MSR */ + "mov $0xC0000082, %%ecx\n" /* IA32_LSTAR MSR */ + "mov %[syscall_handler], %%rax" + "mov %[syscall_handler], %%rdx" + "shr $32, %%rdx\n" + "wrmsr\n" + + /* Write RFLAGS Mask in IA32_LSTAR MSR */ + "mov $0xC0000084, %%ecx\n" /* IA32_FMASK MSR */ + "mov $0x0, %%rax\n" /* RFLAGS Mask lower 32 bits */ + "mov $0x0, %%rdx\n" /* RFLAGS Mask upper 32 bits */ + "wrmsr\n" + + /* Write kernel code segment offset in IA32_STAR MSR */ + "mov $0xC0000081, %%ecx\n" /* IA32_STAR MSR */ + "mov $0x10, %%rax\n" /* kernel code segment offset lower 32 bits */ + "mov $0x0, %%rdx\n" /* kernel code segment offset upper 32 bits */ + "wrmsr\n" + + /* Set SCE bit in MSR_EFER (enabling syscall instruction)*/ + "mov $0xC0000080, %%ecx\n" + "rdmsr\n" + "or $0x1, %%eax\n" + "wrmsr" + : /* no output from call */ + : [syscall_handler] "r"(handler)); + } + } // namespace teachos::arch::context_switching -- cgit v1.2.3 From 187eba4eca3ea46d8c26419168e525242338dae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 13:18:49 +0000 Subject: Simplify syscall setup --- arch/x86_64/src/context_switching/main.cpp | 40 +++++++++--------------------- 1 file changed, 12 insertions(+), 28 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 85cefe5..155d150 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -6,6 +6,7 @@ #include "arch/kernel/cpu/call.hpp" #include "arch/kernel/cpu/control_register.hpp" #include "arch/kernel/cpu/if.hpp" +#include "arch/kernel/cpu/msr.hpp" #include "arch/kernel/cpu/segment_register.hpp" #include "arch/kernel/cpu/tr.hpp" #include "arch/video/vga/text.hpp" @@ -14,6 +15,10 @@ namespace teachos::arch::context_switching { namespace { + auto constexpr IA32_STAR_ADDRESS = 0xC0000081; + auto constexpr IA32_LSTAR_ADDRESS = 0xC0000082; + auto constexpr IA32_FMASK_ADDRESS = 0xC0000084; + constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{ 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; constexpr kernel::cpu::far_pointer KERNEL_CODE_POINTER{&kernel::cpu::reload_data_segment_registers, @@ -74,34 +79,13 @@ namespace teachos::arch::context_switching auto setup_syscall() -> void { - uint64_t handler = reinterpret_cast(syscall_handler); - asm volatile( - /* Write syscall_handler pointer in IA32_LSTAR MSR */ - "mov $0xC0000082, %%ecx\n" /* IA32_LSTAR MSR */ - "mov %[syscall_handler], %%rax" - "mov %[syscall_handler], %%rdx" - "shr $32, %%rdx\n" - "wrmsr\n" - - /* Write RFLAGS Mask in IA32_LSTAR MSR */ - "mov $0xC0000084, %%ecx\n" /* IA32_FMASK MSR */ - "mov $0x0, %%rax\n" /* RFLAGS Mask lower 32 bits */ - "mov $0x0, %%rdx\n" /* RFLAGS Mask upper 32 bits */ - "wrmsr\n" - - /* Write kernel code segment offset in IA32_STAR MSR */ - "mov $0xC0000081, %%ecx\n" /* IA32_STAR MSR */ - "mov $0x10, %%rax\n" /* kernel code segment offset lower 32 bits */ - "mov $0x0, %%rdx\n" /* kernel code segment offset upper 32 bits */ - "wrmsr\n" - - /* Set SCE bit in MSR_EFER (enabling syscall instruction)*/ - "mov $0xC0000080, %%ecx\n" - "rdmsr\n" - "or $0x1, %%eax\n" - "wrmsr" - : /* no output from call */ - : [syscall_handler] "r"(handler)); + uint64_t const syscall_function = reinterpret_cast(syscall_handler); + uint64_t const segment_selector = *reinterpret_cast(&KERNEL_CODE_SEGMENT_SELECTOR); + + kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); + kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); + kernel::cpu::write_msr(IA32_STAR_ADDRESS, segment_selector); + kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); } } // namespace teachos::arch::context_switching -- cgit v1.2.3 From 13dd2bd5a88ec7efeadf8586778f2c5a26d8cd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 14:07:33 +0000 Subject: Move not public methods into anonymous namespace --- arch/x86_64/src/context_switching/main.cpp | 59 +++++++++++++++++++----------- 1 file changed, 38 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 155d150..f73cb19 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,7 +1,6 @@ #include "arch/context_switching/main.hpp" #include "arch/boot/pointers.hpp" -#include "arch/context_switching/syscall_handler.hpp" #include "arch/exception_handling/assert.hpp" #include "arch/kernel/cpu/call.hpp" #include "arch/kernel/cpu/control_register.hpp" @@ -30,6 +29,43 @@ namespace teachos::arch::context_switching auto reload_global_descriptor_table_register() -> void { kernel::cpu::call(KERNEL_CODE_POINTER); } + auto user_mode_main() -> void + { + kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); + + video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); + + asm volatile("syscall"); + + kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); + + video::vga::text::write("Successfully made a SYSCALL and returned back with SYSRET!", + video::vga::text::common_attributes::green_on_black); + } + + auto syscall_handler() -> void + { + uint64_t dummy{}; + switch (dummy) + { + case 0: + break; + default: + break; + } + + asm volatile("sysretq"); + } + + auto enable_systemcall() -> void + { + uint64_t const syscall_function = reinterpret_cast(syscall_handler); + kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); + kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); + kernel::cpu::write_msr(IA32_STAR_ADDRESS, KERNEL_CODE_SEGMENT_SELECTOR); + kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); + } + } // namespace auto initialize_descriptor_tables() -> descriptor_tables @@ -55,17 +91,9 @@ namespace teachos::arch::context_switching return tables; } - auto user_mode_main() -> void - { - kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); - - asm volatile("SYSCALL"); - - video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); - } - auto switch_to_user_mode() -> void { + enable_systemcall(); switch_context(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR, user_mode_main); } @@ -77,15 +105,4 @@ namespace teachos::arch::context_switching kernel::cpu::set_code_segment_register(data_segment, code_segment, reinterpret_cast(return_function)); } - auto setup_syscall() -> void - { - uint64_t const syscall_function = reinterpret_cast(syscall_handler); - uint64_t const segment_selector = *reinterpret_cast(&KERNEL_CODE_SEGMENT_SELECTOR); - - kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); - kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); - kernel::cpu::write_msr(IA32_STAR_ADDRESS, segment_selector); - kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); - } - } // namespace teachos::arch::context_switching -- cgit v1.2.3 From a8a8e09ed39268839ca838c44489bb1352892fef Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 14:11:43 +0000 Subject: merge --- arch/x86_64/src/context_switching/main.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index f73cb19..287ced4 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -104,5 +104,4 @@ namespace teachos::arch::context_switching kernel::cpu::set_data_segment_registers(data_segment); kernel::cpu::set_code_segment_register(data_segment, code_segment, reinterpret_cast(return_function)); } - } // namespace teachos::arch::context_switching -- cgit v1.2.3 From 7c5a40a0de0c5e3ce0a51aa5414c4a433190c60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 14:17:19 +0000 Subject: Add validate methods. For WIP systemcall --- arch/x86_64/src/context_switching/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 287ced4..bd48e18 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -20,6 +20,8 @@ namespace teachos::arch::context_switching constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{ 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + constexpr interrupt_descriptor_table::segment_selector KERNEL_DATA_SEGMENT_SELECTOR{ + 2U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; constexpr kernel::cpu::far_pointer KERNEL_CODE_POINTER{&kernel::cpu::reload_data_segment_registers, KERNEL_CODE_SEGMENT_SELECTOR}; constexpr context_switching::interrupt_descriptor_table::segment_selector USER_CODE_SEGMENT_SELECTOR{ @@ -45,6 +47,8 @@ namespace teachos::arch::context_switching auto syscall_handler() -> void { + kernel::cpu::validate_segment_registers(KERNEL_CODE_SEGMENT_SELECTOR, KERNEL_DATA_SEGMENT_SELECTOR); + uint64_t dummy{}; switch (dummy) { -- cgit v1.2.3 From 95c299db969b29eb4a4742ff7715adecfe138bd5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 14:43:31 +0000 Subject: test different values --- arch/x86_64/src/context_switching/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 287ced4..4e13b1c 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -62,7 +62,16 @@ namespace teachos::arch::context_switching uint64_t const syscall_function = reinterpret_cast(syscall_handler); kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); + + uint64_t kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR; // Your 64-bit kernel code segment selector + uint64_t user_cs = USER_CODE_SEGMENT_SELECTOR + 0x3; // User mode code segment selector (RPL=3) + + uint64_t star_value = (user_cs << 48) | (kernel_cs << 32); + + kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value); kernel::cpu::write_msr(IA32_STAR_ADDRESS, KERNEL_CODE_SEGMENT_SELECTOR); + + // kernel::cpu::write_msr(IA32_STAR_ADDRESS, KERNEL_CODE_SEGMENT_SELECTOR); kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); } -- cgit v1.2.3 From adb66c18b9e6ca0f65934f453afda1c5f9fe145f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 15:14:04 +0000 Subject: wip enable syscall --- arch/x86_64/src/context_switching/main.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 33af765..21299da 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -33,22 +33,16 @@ namespace teachos::arch::context_switching auto user_mode_main() -> void { - kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); - video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); asm volatile("syscall"); - kernel::cpu::validate_segment_registers(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR); - - video::vga::text::write("Successfully made a SYSCALL and returned back with SYSRET!", + video::vga::text::write("Successfully made a SYSCALL and returned back with SYSRETQ!", video::vga::text::common_attributes::green_on_black); } auto syscall_handler() -> void { - kernel::cpu::validate_segment_registers(KERNEL_CODE_SEGMENT_SELECTOR, KERNEL_DATA_SEGMENT_SELECTOR); - uint64_t dummy{}; switch (dummy) { @@ -65,17 +59,19 @@ namespace teachos::arch::context_switching { uint64_t const syscall_function = reinterpret_cast(syscall_handler); kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); - kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); - - uint64_t kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR; // Your 64-bit kernel code segment selector - uint64_t user_cs = USER_CODE_SEGMENT_SELECTOR + 0x3; // User mode code segment selector (RPL=3) - - uint64_t star_value = (user_cs << 48) | (kernel_cs << 32); - + kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 1 << 9U); // Disable interrupt flag during syscall + + // @MTO: This produces following values: + // After SYSCALL: CS = 0x10, SS = 0x18 + // After SYSRETQ: CS = 0x43, SS = 0x3b + // + // We probably need to modify our GDT, because the cs+8 = ss is an issue we cannot solve. + // Also, CS = 0x43 is weird. I expected it to be 0x33. + uint64_t kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR; + uint64_t user_cs = USER_CODE_SEGMENT_SELECTOR; + uint64_t star_value = (kernel_cs << 32) | (user_cs << 48); kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value); - kernel::cpu::write_msr(IA32_STAR_ADDRESS, KERNEL_CODE_SEGMENT_SELECTOR); - // kernel::cpu::write_msr(IA32_STAR_ADDRESS, KERNEL_CODE_SEGMENT_SELECTOR); kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); } -- cgit v1.2.3 From ecdfbc3e1458923f619f0d4b8a841a6e96a6678a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Apr 2025 15:01:44 +0000 Subject: Start adding parameters to syscall --- arch/x86_64/src/context_switching/main.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 21299da..2a2a188 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -35,6 +35,11 @@ namespace teachos::arch::context_switching { video::vga::text::write("Successfully entered user mode!", video::vga::text::common_attributes::green_on_black); + uint64_t new_value = 60U; + asm volatile("mov %[input], %%rax" + : /* no output from call */ + : [input] "r"(new_value) +