diff options
| author | Fabian Imhof <fabian.imhof@ost.ch> | 2025-04-05 15:27:20 +0000 |
|---|---|---|
| committer | Fabian Imhof <fabian.imhof@ost.ch> | 2025-04-05 15:27:20 +0000 |
| commit | a8852f91967a7e55e62e30f5cc07d076092b8b78 (patch) | |
| tree | 12708befd57fc0b89dbadc2e856c935b71c88807 /arch | |
| parent | c01d080bdc6bd843e840e4834424fe587286b274 (diff) | |
| download | teachos-a8852f91967a7e55e62e30f5cc07d076092b8b78.tar.xz teachos-a8852f91967a7e55e62e30f5cc07d076092b8b78.zip | |
add wip context switch to user mode
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86_64/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/boot/pointers.hpp | 5 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/kernel/cpu/segment_register.hpp | 23 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/kernel/cpu/ss.hpp | 27 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/boot.s | 11 | ||||
| -rw-r--r-- | arch/x86_64/src/context_switching/main.cpp | 4 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/cpu/segment_register.cpp | 34 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/cpu/ss.cpp | 16 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 35 |
9 files changed, 96 insertions, 61 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 5e87594..0d52463 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -13,7 +13,7 @@ target_sources("_kernel" PRIVATE "src/kernel/cpu/if.cpp" "src/kernel/cpu/jmp.cpp" "src/kernel/cpu/msr.cpp" - "src/kernel/cpu/ss.cpp" + "src/kernel/cpu/segment_register.cpp" "src/kernel/cpu/tlb.cpp" "src/kernel/cpu/tr.cpp" ) diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 9bf5cfd..fe9c657 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -10,11 +10,6 @@ namespace teachos::arch::boot */ extern "C" size_t const multiboot_information_pointer; - /** - * @brief Address pointing to the method that clears all segment registers. - */ - extern "C" void reload_segment_register(); - } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp new file mode 100644 index 0000000..bd244fd --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP + +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Clear all segment registers. + */ + [[gnu::naked]] + auto reload_segment_registers() -> void; + + /** + * @brief Set the value of all segment registers. + * + * @param segment_selector + */ + auto set_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/ss.hpp b/arch/x86_64/include/arch/kernel/cpu/ss.hpp deleted file mode 100644 index b5fa5e3..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/ss.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP - -#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" - -#include <bitset> -#include <cstdint> - -namespace teachos::arch::kernel::cpu -{ - /** - * @brief Reads the current value of the stack segment (SS) register. - * - * @return The current SS register value. - */ - auto read_ss() -> context_switching::interrupt_descriptor_table::segment_selector; - - /** - * @brief Writes a new value to the stack segment (SS) register. - * - * @param selector The segment selector to be written to SS. - */ - auto write_ss(context_switching::interrupt_descriptor_table::segment_selector selector) -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s index 38a8af4..7932045 100644 --- a/arch/x86_64/src/boot/boot.s +++ b/arch/x86_64/src/boot/boot.s @@ -352,11 +352,7 @@ prepare_page_maps: .section .boot_text, "ax", @progbits .code64 -.global reload_segment_register -reload_segment_register: - // FIXME: maybe we should set the actually correct values here. We'd need to communicate them down from C++. - // Alternatively, we could probably implement this as a [[gnu::naked]] function in C++, to have easier access to - // arguments and symbols. Maybe later. +_transition_to_long_mode: xor %rax, %rax mov %rax, %ss mov %rax, %ds @@ -364,11 +360,6 @@ reload_segment_register: mov %rax, %fs mov %rax, %gs - ret - -_transition_to_long_mode: - call reload_segment_register - movl $0xb8000, (vga_buffer_pointer) call _init 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(); diff --git a/arch/x86_64/src/kernel/cpu/segment_register.cpp b/arch/x86_64/src/kernel/cpu/segment_register.cpp new file mode 100644 index 0000000..f70c558 --- /dev/null +++ b/arch/x86_64/src/kernel/cpu/segment_register.cpp @@ -0,0 +1,34 @@ +#include "arch/kernel/cpu/segment_register.hpp" + +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + +namespace teachos::arch::kernel::cpu +{ + [[gnu::naked]] + auto reload_segment_registers() -> void + { + asm volatile("xor %rax, %rax\n" + "mov %rax, %ss\n" + "mov %rax, %ds\n" + "mov %rax, %es\n" + "mov %rax, %fs\n" + "mov %rax, %gs\n" + "ret"); + } + + [[gnu::naked]] + auto set_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void + { + asm volatile("xor %%rax, %%rax\n" + "mov %[input], %%ax\n" + "mov %%rax, %%ss\n" + "mov %%rax, %%ds\n" + "mov %%rax, %%es\n" + "mov %%rax, %%fs\n" + "mov %%rax, %%gs\n" + "ret" + : /* No output from call */ + : [input] "m"(segment_selector)); + } + +} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/kernel/cpu/ss.cpp b/arch/x86_64/src/kernel/cpu/ss.cpp deleted file mode 100644 index 0978eca..0000000 --- a/arch/x86_64/src/kernel/cpu/ss.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "arch/kernel/cpu/ss.hpp" - -namespace teachos::arch::kernel::cpu -{ - auto read_ss() -> context_switching::interrupt_descriptor_table::segment_selector - { - context_switching::interrupt_descriptor_table::segment_selector segment_selector{}; - asm volatile("mov %%ss, %[output]" : [output] "=m"(segment_selector)); - return segment_selector; - } - - auto write_ss(context_switching::interrupt_descriptor_table::segment_selector selector) -> void - { - asm volatile("mov %[input], %%ss" : /* no output from call */ : [input] "m"(selector)); - } -} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index 7782d30..7d4173e 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -1,9 +1,11 @@ #include "arch/kernel/main.hpp" #include "arch/boot/pointers.hpp" +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" #include "arch/context_switching/main.hpp" #include "arch/kernel/cpu/if.hpp" #include "arch/kernel/cpu/jmp.hpp" +#include "arch/kernel/cpu/segment_register.hpp" #include "arch/memory/heap/bump_allocator.hpp" #include "arch/memory/heap/global_heap_allocator.hpp" #include "arch/memory/main.hpp" @@ -49,6 +51,23 @@ namespace teachos::arch::kernel delete test9; } + [[gnu::naked]] + auto push_code_segment(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void + { + asm volatile("push %%rbp\n" + "push %[input]" + : /* No output from call */ + : [input] "m"(segment_selector)); + } + + [[gnu::naked]] + auto iret() -> void + { + asm volatile("iret" + : /* No output from call */ + : /* No input to call */); + } + auto main() -> void { video::vga::text::clear(); @@ -64,6 +83,22 @@ namespace teachos::arch::kernel heap_test(); decltype(auto) descriptor_tables = context_switching::initialize_descriptor_tables(); + + // - Clear NT flag in EFLAGS register (for far return) + + // - 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); + + // IRET + iret(); + (void)descriptor_tables; } } // namespace teachos::arch::kernel |
