diff options
| author | Fabian Imhof <fabian.imhof@ost.ch> | 2025-04-06 07:47:27 +0000 |
|---|---|---|
| committer | Fabian Imhof <fabian.imhof@ost.ch> | 2025-04-06 07:47:27 +0000 |
| commit | 350aedae0e50749f9821ac7dc6b8316cf35f24bb (patch) | |
| tree | 21f3c67a1648d5950718dc5b0db32e45b870641f | |
| parent | a8852f91967a7e55e62e30f5cc07d076092b8b78 (diff) | |
| download | teachos-350aedae0e50749f9821ac7dc6b8316cf35f24bb.tar.xz teachos-350aedae0e50749f9821ac7dc6b8316cf35f24bb.zip | |
wip context switch in asm
| -rw-r--r-- | arch/x86_64/include/arch/boot/pointers.hpp | 1 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/boot.s | 29 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 31 |
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; } |
