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.cpp58
1 files changed, 40 insertions, 18 deletions
diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp
index 5901998..7449d84 100644
--- a/arch/x86_64/src/context_switching/main.cpp
+++ b/arch/x86_64/src/context_switching/main.cpp
@@ -31,14 +31,14 @@ namespace teachos::arch::context_switching
auto reload_gdtr() -> void
{
- // asm volatile("pushq $0x8\n\t" // Push new CS
- // "lea 1f(%%rip), %%rax\n\t" // Get address of label 1 into RAX
- // "pushq %%rax\n\t" // Push return address
- // "lretq\n" // Far return (loads CS:RIP)
- // "1:\n\t" // Label to return to
- // :
- // :
- // : "rax", "memory");
+ /*asm volatile("pushq $0x8\n\t" // Push new CS
+ "lea 1f(%%rip), %%rax\n\t" // Get address of label 1 into RAX
+ "pushq %%rax\n\t" // Push return address
+ "lretq\n" // Far return (loads CS:RIP)
+ "1:\n\t" // Label to return to
+ :
+ :
+ : "rax", "memory");*/
kernel::cpu::call(KERNEL_CODE_POINTER);
}
@@ -57,21 +57,33 @@ namespace teachos::arch::context_switching
// 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
- uint64_t new_value = 60U;
+ uint64_t syscall_number = 60U;
asm volatile("mov %[input], %%rax"
: /* no output from call */
- : [input] "r"(new_value)
+ : [input] "r"(syscall_number)
: "memory");
asm volatile("syscall");
- video::vga::text::write("Successfully made a SYSCALL and returned with SYSRETQ!",
- video::vga::text::common_attributes::green_on_black);
+ // TODO: Reading RAX value does not work because the read itself changes the RAX value?!
+ // asm volatile("mov %%rax, %[output]" : [output] "=r"(syscall_value));
+
+ // TODO: Causes a general protection fault after the sysreturn?
+ // If removed instead it will cause a general protection fault after leaving this main method to return to kernel
+ // mode. But CS and SS are still configured for User mode.
+ /*video::vga::text::write("Successfully made a SYSCALL and returned with SYSRETQ!",
+ video::vga::text::common_attributes::green_on_black);*/
}
auto syscall_handler() -> void
{
- uint64_t syscall_number{};
+ uint64_t syscall_number, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5 = {};
asm volatile("mov %%rax, %[output]" : [output] "=r"(syscall_number));
+ asm volatile("mov %%rdi, %[output]" : [output] "=r"(arg_0));
+ asm volatile("mov %%rsi, %[output]" : [output] "=r"(arg_1));
+ asm volatile("mov %%rdx, %[output]" : [output] "=r"(arg_2));
+ asm volatile("mov %%r10, %[output]" : [output] "=r"(arg_3));
+ asm volatile("mov %%r8, %[output]" : [output] "=r"(arg_4));
+ asm volatile("mov %%r9, %[output]" : [output] "=r"(arg_5));
switch (syscall_number)
{
@@ -85,7 +97,17 @@ namespace teachos::arch::context_switching
break;
}
- asm volatile("sysretq");
+ uint64_t result = 0U;
+ asm volatile("mov %[input], %%rax"
+ : /* no output from call */
+ : [input] "r"(result)
+ : "memory");
+
+ // Use SYSRET instead of SYSRETQ, because the latter would add 0x10 to bits [48:63] of IA32_STAR_ADDRESS for the
+ // Code Segment. But only add 0x8 to bits [48:63] of IA32_STAR_ADDRESS for the Stack Segment, which means either
+ // the Stack Segment or Code Segment is wrong. Whereas the former does not add 0x10 for the Code Segment and
+ // therefore fixes the aformentioned issue.
+ asm volatile("sysret");
}
auto enable_systemcall() -> void
@@ -94,9 +116,9 @@ namespace teachos::arch::context_switching
kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function);
kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U);
- uint64_t kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR;
- uint64_t user_cs = KERNEL_CODE_SEGMENT_SELECTOR;
- uint64_t star_value = (kernel_cs << 32) | (user_cs << 48);
+ uint64_t const kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR;
+ uint64_t const user_cs = USER_CODE_SEGMENT_SELECTOR;
+ uint64_t const star_value = (kernel_cs << 32) | (user_cs << 48);
kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value);
kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE);
@@ -116,7 +138,7 @@ namespace teachos::arch::context_switching
interrupt_descriptor_table::update_interrupt_descriptor_table_register();
reload_gdtr();
- segment_descriptor_table::update_task_state_segment_register();
+ segment_descriptor_table::update_tss_register();
kernel::cpu::set_interrupt_flag();
initalized = true;