aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2025-04-27 11:20:02 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2025-04-27 11:20:02 +0000
commit7261c64bb236a313ed8846a9c9dbded6890a9e98 (patch)
tree3f43ab7d1e87025dd622bbc9cd56aad5d37a2f78 /arch/x86_64/src
parentc865eff02ae1978b4f665432d853374d1ffacecf (diff)
downloadteachos-7261c64bb236a313ed8846a9c9dbded6890a9e98.tar.xz
teachos-7261c64bb236a313ed8846a9c9dbded6890a9e98.zip
wip implement syscall in cpp
Diffstat (limited to 'arch/x86_64/src')
-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
4 files changed, 55 insertions, 34 deletions
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