aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/context_switching/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/context_switching/main.cpp')
-rw-r--r--arch/x86_64/src/context_switching/main.cpp43
1 files changed, 34 insertions, 9 deletions
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