aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2025-04-06 07:47:27 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2025-04-06 07:47:27 +0000
commit350aedae0e50749f9821ac7dc6b8316cf35f24bb (patch)
tree21f3c67a1648d5950718dc5b0db32e45b870641f
parenta8852f91967a7e55e62e30f5cc07d076092b8b78 (diff)
downloadteachos-350aedae0e50749f9821ac7dc6b8316cf35f24bb.tar.xz
teachos-350aedae0e50749f9821ac7dc6b8316cf35f24bb.zip
wip context switch in asm
-rw-r--r--arch/x86_64/include/arch/boot/pointers.hpp1
-rw-r--r--arch/x86_64/src/boot/boot.s29
-rw-r--r--arch/x86_64/src/kernel/main.cpp31
3 files changed, 50 insertions, 11 deletions
diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp
index fe9c657..f0878f9 100644
--- a/arch/x86_64/include/arch/boot/pointers.hpp
+++ b/arch/x86_64/include/arch/boot/pointers.hpp
@@ -9,6 +9,7 @@ namespace teachos::arch::boot
* @brief Address pointing to the start of the multiboot information structure.
*/
extern "C" size_t const multiboot_information_pointer;
+ extern "C" auto context_switch() -> void;
} // namespace teachos::arch::boot
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
index 7932045..85ae1a1 100644
--- a/arch/x86_64/src/boot/boot.s
+++ b/arch/x86_64/src/boot/boot.s
@@ -352,6 +352,35 @@ prepare_page_maps:
.section .boot_text, "ax", @progbits
.code64
+.global context_switch
+context_switch:
+ // ring 3 data with bottom 2 bits set for ring 3
+ mov $((4 * 16) | 3), %rax
+ mov %rax, %ds
+ mov %rax, %es
+ mov %rax, %fs
+ mov %rax, %gs
+ // SS is handled by iret https://wiki.osdev.org/Getting_to_Ring_3
+
+ // set up the stack frame iret expects
+ mov %rsp, %rax
+ // user data selector
+ push $((4 * 16) | 3)
+ // current exp
+ push %rax
+ // push eflags
+ pushf
+ // push code selector (ring 3 code with bottom 2 bits set for ring 3)
+ push $((3 * 16) | 3)
+ // instruction address to return to
+ push test_function
+
+ iret
+
+test_function:
+ cli
+ ret
+
_transition_to_long_mode:
xor %rax, %rax
mov %rax, %ss
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index 7d4173e..52799f0 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -52,12 +52,24 @@ namespace teachos::arch::kernel
}
[[gnu::naked]]
- auto push_code_segment(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void
+ auto push_code_segment(context_switching::interrupt_descriptor_table::segment_selector segment_selector_a,
+ context_switching::interrupt_descriptor_table::segment_selector segment_selector_b) -> void
{
asm volatile("push %%rbp\n"
"push %[input]"
: /* No output from call */
- : [input] "m"(segment_selector));
+ : [input] "m"(segment_selector_a));
+ asm volatile("mov %[input], %%ax\n"
+ "mov %%ax, %%ss\n"
+ "mov %%ax, %%ds\n"
+ "mov %%ax, %%es\n"
+ "mov %%ax, %%fs\n"
+ "mov %%ax, %%gs"
+ : /* No output from call */
+ : [input] "m"(segment_selector_b));
+ asm volatile("iret"
+ : /* No output from call */
+ : /* No input to call */);
}
[[gnu::naked]]
@@ -88,16 +100,13 @@ namespace teachos::arch::kernel
// - Push return instruction pointer
// - Push return code segment selector
- context_switching::interrupt_descriptor_table::segment_selector user_code_segment_selector{
- 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
- push_code_segment(user_code_segment_selector);
-
- context_switching::interrupt_descriptor_table::segment_selector user_data_segment_selector{
- 4U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
- kernel::cpu::set_segment_registers(user_data_segment_selector);
+ // context_switching::interrupt_descriptor_table::segment_selector user_code_segment_selector{
+ // 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
+ // context_switching::interrupt_descriptor_table::segment_selector user_data_segment_selector{
+ // 4U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
+ // push_code_segment(user_code_segment_selector, user_data_segment_selector);
- // IRET
- iret();
+ boot::context_switch();
(void)descriptor_tables;
}