diff options
10 files changed, 73 insertions, 59 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 1ce2731..3d6d2c7 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -101,6 +101,7 @@ target_sources("_context" PRIVATE "src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp" "src/context_switching/main.cpp" "src/context_switching/syscall/main.cpp" + "src/context_switching/syscall/syscall_enable.cpp" "src/context_switching/syscall/syscall_handler.cpp" "src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp" "src/context_switching/interrupt_descriptor_table/idt_flags.cpp" diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index c75268a..ae4c2db 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -1,14 +1,22 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP -#include "arch/context_switching/syscall/syscall_handler.hpp" - -#include <array> #include <cstdint> -#include <optional> namespace teachos::arch::context_switching::syscall { + enum class type : uint64_t + { + WRITE = 1U + }; + + enum class error + { + OK = 0U, + }; + + constexpr bool operator!(error e) { return e == error::OK; } + struct arguments { uint64_t arg_0{}; @@ -19,9 +27,7 @@ namespace teachos::arch::context_switching::syscall uint64_t arg_5{}; }; - auto enable_syscall() -> void; - - auto syscall(type syscall_number, arguments args = {}) -> uint64_t; + auto syscall(type syscall_number, arguments args = {}) -> error; } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp new file mode 100644 index 0000000..59b97b2 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp @@ -0,0 +1,10 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP + +namespace teachos::arch::context_switching::syscall +{ + auto enable_syscall() -> void; + +} // namespace teachos::arch::context_switching::syscall + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp index e076995..2e7bcd1 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp @@ -5,16 +5,11 @@ namespace teachos::arch::context_switching::syscall { - enum type : uint64_t - { - WRITE = 1U - }; - /** * @brief Handler for SYSCALL instruction. Calls a specific implementation based * on the register RAX. * - * @return Returns with SYSRETQ + * @return Returns with LEAVE, SYSRETQ */ auto syscall_handler() -> void; diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp index 7127d07..4f1d005 100644 --- a/arch/x86_64/include/arch/user/main.hpp +++ b/arch/x86_64/include/arch/user/main.hpp @@ -7,4 +7,4 @@ namespace teachos::arch::user } // namespace teachos::arch::user -#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP
\ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index a112924..9539428 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -1,15 +1,12 @@ #include "arch/context_switching/main.hpp" #include "arch/boot/pointers.hpp" -#include "arch/context_switching/syscall/main.hpp" -#include "arch/exception_handling/assert.hpp" +#include "arch/context_switching/syscall/syscall_enable.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" #include "arch/user/main.hpp" -#include "arch/video/vga/text.hpp" namespace teachos::arch::context_switching { diff --git a/arch/x86_64/src/context_switching/syscall/main.cpp b/arch/x86_64/src/context_switching/syscall/main.cpp index 9ac63ce..a226e23 100644 --- a/arch/x86_64/src/context_switching/syscall/main.cpp +++ b/arch/x86_64/src/context_switching/syscall/main.cpp @@ -1,39 +1,8 @@ #include "arch/context_switching/syscall/main.hpp" -#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" -#include "arch/exception_handling/assert.hpp" -#include "arch/exception_handling/panic.hpp" -#include "arch/kernel/cpu/msr.hpp" - -#include <cstdint> - namespace teachos::arch::context_switching::syscall { - namespace - { - constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{ - 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; - - auto constexpr IA32_STAR_ADDRESS = 0xC0000081; - auto constexpr IA32_LSTAR_ADDRESS = 0xC0000082; - auto constexpr IA32_FMASK_ADDRESS = 0xC0000084; - - } // namespace - - auto enable_syscall() -> void - { - uint64_t const syscall_function = reinterpret_cast<uint64_t>(syscall_handler); - kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); - kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); - - uint64_t const kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR; - uint64_t const star_value = (kernel_cs << 32) | (kernel_cs << 48); - kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value); - - kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); - } - - auto syscall(type syscall_number, arguments args) -> uint64_t + auto syscall(type syscall_number, arguments args) -> error { asm volatile("mov %[input], %%rax" : /* no output from call */ @@ -49,7 +18,7 @@ namespace teachos::arch::context_switching::syscall asm volatile("syscall"); - uint64_t error{}; + error error{}; asm volatile("mov %%rax, %[output]" : [output] "=m"(error)); return error; } diff --git a/arch/x86_64/src/context_switching/syscall/syscall_enable.cpp b/arch/x86_64/src/context_switching/syscall/syscall_enable.cpp new file mode 100644 index 0000000..e6265d3 --- /dev/null +++ b/arch/x86_64/src/context_switching/syscall/syscall_enable.cpp @@ -0,0 +1,32 @@ +#include "arch/context_switching/syscall/syscall_enable.hpp" + +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" +#include "arch/context_switching/syscall/syscall_handler.hpp" +#include "arch/kernel/cpu/msr.hpp" + +namespace teachos::arch::context_switching::syscall +{ + namespace + { + constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{ + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + + auto constexpr IA32_STAR_ADDRESS = 0xC0000081; + auto constexpr IA32_LSTAR_ADDRESS = 0xC0000082; + auto constexpr IA32_FMASK_ADDRESS = 0xC0000084; + + } // namespace + + auto enable_syscall() -> void + { + uint64_t const syscall_function = reinterpret_cast<uint64_t>(syscall_handler); + kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function); + kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U); + + uint64_t const kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR; + uint64_t const star_value = (kernel_cs << 32) | (kernel_cs << 48); + kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value); + + kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE); + } +} // namespace teachos::arch::context_switching::syscall
\ No newline at end of file diff --git a/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp b/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp index 759a092..fbfecc0 100644 --- a/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp +++ b/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp @@ -1,5 +1,6 @@ #include "arch/context_switching/syscall/syscall_handler.hpp" +#include "arch/context_switching/syscall/main.hpp" #include "arch/exception_handling/panic.hpp" #include "arch/video/vga/text.hpp" @@ -8,11 +9,12 @@ namespace teachos::arch::context_switching::syscall namespace { - auto write_to_vga_buffer(uint64_t buffer) + auto write_to_vga_buffer(uint64_t buffer) -> error { video::vga::text::write(reinterpret_cast<const char *>(buffer), video::vga::text::common_attributes::green_on_black); video::vga::text::newline(); + return error::OK; } } // namespace @@ -38,17 +40,17 @@ namespace teachos::arch::context_switching::syscall // and now. asm volatile("mov %%rax, %[output]" : [output] "=m"(syscall_number)); + error result = error::OK; switch (static_cast<type>(syscall_number)) { - case WRITE: - write_to_vga_buffer(arg_0); + case type::WRITE: + result = write_to_vga_buffer(arg_0); break; default: teachos::arch::exception_handling::panic("[Syscall Handler] Invalid syscall number"); break; } - uint64_t result = 0U; asm volatile("mov %[input], %%rax" : /* no output from call */ : [input] "m"(result) @@ -63,6 +65,9 @@ namespace teachos::arch::context_switching::syscall : [input] "m"(rflags) : "memory"); + // Additionally call leave, because x86 allocates tack space for the internal variables. If we do not clean up this + // newly created stack frame the syscall instruction that landed in this syscall_handler, will never return to the + // method that originally called it, becuase the RIP has not been restored from the previous stack frame. asm volatile("leave\n" "sysretq"); } diff --git a/arch/x86_64/src/user/main.cpp b/arch/x86_64/src/user/main.cpp index 6d8eea7..8ce21ba 100644 --- a/arch/x86_64/src/user/main.cpp +++ b/arch/x86_64/src/user/main.cpp @@ -7,7 +7,6 @@ namespace teachos::arch::user { - [[gnu::section(".user_text")]] auto main() -> void { @@ -23,9 +22,9 @@ namespace teachos::arch::user // Actual Source: https://man7.org/linux/man-pages/man2/syscall.2.html More cleare documentation: // https://sys.readthedocs.io/en/latest/doc/05_calling_system_calls.html - const char syscall_message[68] = "Successfully entered user mode and wrote to VGA buffer via syscall!"; - auto error = context_switching::syscall::syscall(context_switching::syscall::WRITE, - {reinterpret_cast<uint64_t>(&syscall_message)}); + char constexpr syscall_message[] = "Successfully entered user mode and wrote to VGA buffer via syscall!"; + auto const error = context_switching::syscall::syscall(context_switching::syscall::type::WRITE, + {reinterpret_cast<uint64_t>(&syscall_message)}); if (!error) { |
