From 099a7fbbc35a71f98553fa39899f2d17c555242f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 2 May 2025 14:49:06 +0000 Subject: Finish implementing 8-byte GDT entries and syscall arg loads. --- arch/x86_64/src/context_switching/main.cpp | 58 ++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/src/context_switching/main.cpp') 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; -- cgit v1.2.3