aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/CMakeLists.txt1
-rw-r--r--arch/x86_64/include/arch/boot/pointers.hpp2
-rw-r--r--arch/x86_64/include/arch/context_switching/main.hpp2
-rw-r--r--arch/x86_64/include/arch/context_switching/syscall_handler.hpp8
-rw-r--r--arch/x86_64/src/boot/boot.s25
-rw-r--r--arch/x86_64/src/context_switching/main.cpp43
-rw-r--r--arch/x86_64/src/context_switching/syscall_handler.cpp20
-rw-r--r--arch/x86_64/src/kernel/main.cpp1
8 files changed, 66 insertions, 36 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 71b1946..d5fb913 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -105,6 +105,7 @@ target_sources("_context" PRIVATE
"src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp"
"src/context_switching/interrupt_descriptor_table/ist_offset.cpp"
"src/context_switching/interrupt_descriptor_table/segment_selector.cpp"
+ "src/context_switching/syscall_handler.cpp"
)
#[============================================================================[
diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp
index d9a7ab7..fe9c657 100644
--- a/arch/x86_64/include/arch/boot/pointers.hpp
+++ b/arch/x86_64/include/arch/boot/pointers.hpp
@@ -10,8 +10,6 @@ namespace teachos::arch::boot
*/
extern "C" size_t const multiboot_information_pointer;
- extern "C" void syscall_trampoline();
-
} // namespace teachos::arch::boot
#endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP
diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp
index f8477ea..5537174 100644
--- a/arch/x86_64/include/arch/context_switching/main.hpp
+++ b/arch/x86_64/include/arch/context_switching/main.hpp
@@ -46,6 +46,8 @@ 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;
+ auto setup_syscall() -> void;
+
} // namespace teachos::arch::context_switching
#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
diff --git a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp
new file mode 100644
index 0000000..8583051
--- /dev/null
+++ b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp
@@ -0,0 +1,8 @@
+#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP
+#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP
+
+namespace teachos::arch::context_switching
+{
+ auto syscall_handler() -> void;
+}
+#endif \ No newline at end of file
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
index 24b38ca..7932045 100644
--- a/arch/x86_64/src/boot/boot.s
+++ b/arch/x86_64/src/boot/boot.s
@@ -352,31 +352,6 @@ prepare_page_maps:
.section .boot_text, "ax", @progbits
.code64
-syscall_target:
- iretq
-
-.global syscall_trampoline
-syscall_trampoline:
- /* Write target function pointer in IA32_LSTAR MSR */
- mov $0xC0000082, %ecx /* IA32_LSTAR MSR */
- lea [syscall_target], %rax
- lea [syscall_target], %rdx
- shr $32, %rdx
- wrmsr
-
- /* Write ... in IA32_LSTAR MSR */
- mov $0xC0000084, %ecx /* IA32_FMASK MSR */
- mov $0x0, %rax /* ... lower 32 bits */
- mov $0x0, %rdx /* ... upper 32 bits */
- wrmsr
-
- /* Write Segment selector in IA32_STAR MSR */
- mov $0xC0000081, %ecx /* IA32_STAR MSR */
- mov $0x10, %rax /* SS lower 32 bits */
- mov $0x0, %rdx /* SS upper 32 bits */
- wrmsr
-
-
_transition_to_long_mode:
xor %rax, %rax
mov %rax, %ss
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<uint64_t>(return_function));
}
+ auto setup_syscall() -> void
+ {
+ uint64_t handler = reinterpret_cast<uint64_t>(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
diff --git a/arch/x86_64/src/context_switching/syscall_handler.cpp b/arch/x86_64/src/context_switching/syscall_handler.cpp
new file mode 100644
index 0000000..1bc4ef9
--- /dev/null
+++ b/arch/x86_64/src/context_switching/syscall_handler.cpp
@@ -0,0 +1,20 @@
+#include "arch/context_switching/syscall_handler.hpp"
+
+#include <cstdint>
+
+namespace teachos::arch::context_switching
+{
+ [[gnu::naked]]
+ auto syscall_handler() -> void
+ {
+ uint64_t dummy{};
+ switch (dummy)
+ {
+ case 0:
+ break;
+ default:
+ break;
+ }
+ asm volatile("SYSRET");
+ }
+} // namespace teachos::arch::context_switching \ No newline at end of file
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index 05c879e..e737d44 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -63,6 +63,7 @@ namespace teachos::arch::kernel
memory::heap::global_heap_allocator::register_heap_allocator(memory::heap::heap_allocator_type::LINKED_LIST);
// heap_test();
+ context_switching::setup_syscall();
context_switching::switch_to_user_mode();
}
} // namespace teachos::arch::kernel