From 41d5a2a786726b3655b0dd444b77b76ab1aa45f3 Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Fri, 6 Aug 2021 18:08:04 +0200
Subject: [PATCH] Use naked functions in syscall inst handler too.

---
 src/arch/x86_64/gdt.rs               |  3 ---
 src/arch/x86_64/interrupt/handler.rs | 28 -------------------
 src/arch/x86_64/interrupt/syscall.rs | 40 +++++++++++++++++++---------
 3 files changed, 27 insertions(+), 44 deletions(-)

diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs
index 5e974c3d..b55db056 100644
--- a/src/arch/x86_64/gdt.rs
+++ b/src/arch/x86_64/gdt.rs
@@ -78,9 +78,6 @@ pub static mut GDT: [GdtEntry; 10] = [
 
 #[repr(C, align(16))]
 pub struct ProcessorControlRegion {
-    // NOTE: If you plan to change any fields here, please make sure that you also modify the
-    // offsets in the syscall instruction handler accordingly!
-
     pub tcb_end: usize,
     pub user_rsp_tmp: usize,
     pub tss: TssWrapper,
diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs
index 58ee4dd7..4cf27e87 100644
--- a/src/arch/x86_64/interrupt/handler.rs
+++ b/src/arch/x86_64/interrupt/handler.rs
@@ -203,34 +203,6 @@ impl InterruptErrorStack {
     }
 }
 
-#[macro_export]
-macro_rules! intel_asm {
-    ($($strings:expr,)+) => {
-        global_asm!(concat!(
-            $($strings),+,
-        ));
-    };
-}
-#[macro_export]
-macro_rules! function {
-    ($name:ident => { $($body:expr,)+ }) => {
-        intel_asm!(
-            ".global ", stringify!($name), "\n",
-            ".type ", stringify!($name), ", @function\n",
-            ".section .text.", stringify!($name), ", \"ax\", @progbits\n",
-            // Align the function to a 16-byte boundary, padding with multi-byte NOPs.
-            ".p2align 4,,15\n",
-            stringify!($name), ":\n",
-            $($body),+,
-            ".size ", stringify!($name), ", . - ", stringify!($name), "\n",
-            ".text\n",
-        );
-        extern "C" {
-            pub fn $name();
-        }
-    };
-}
-
 #[macro_export]
 macro_rules! push_scratch {
     () => { "
diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs
index 3fbc49ac..38c78c23 100644
--- a/src/arch/x86_64/interrupt/syscall.rs
+++ b/src/arch/x86_64/interrupt/syscall.rs
@@ -5,7 +5,8 @@ use crate::{
     syscall,
     syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL},
 };
-use x86::msr;
+use memoffset::offset_of;
+use x86::{bits64::task::TaskStateSegment, msr, segmentation::SegmentSelector};
 
 pub unsafe fn init() {
     // IA32_STAR[31:0] are reserved.
@@ -58,16 +59,18 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
     });
 }
 
-function!(syscall_instruction => {
+#[naked]
+pub unsafe extern "C" fn syscall_instruction() {
+    asm!(concat!(
     // Yes, this is magic. No, you don't need to understand
     "
         swapgs                    // Set gs segment to TSS
-        mov gs:[0x08], rsp        // Save userspace stack pointer
-        mov rsp, gs:[0x14]        // Load kernel stack pointer
-        push QWORD PTR 5 * 8 + 3  // Push fake userspace SS (resembling iret frame)
-        push QWORD PTR gs:[0x08]  // Push userspace rsp
+        mov gs:[{sp}], rsp        // Save userspace stack pointer
+        mov rsp, gs:[{ksp}]       // Load kernel stack pointer
+        push QWORD PTR {ss_sel}   // Push fake userspace SS (resembling iret frame)
+        push QWORD PTR gs:[{sp}]  // Push userspace rsp
         push r11                  // Push rflags
-        push QWORD PTR 6 * 8 + 3  // Push fake CS (resembling iret stack frame)
+        push QWORD PTR {cs_sel}   // Push fake CS (resembling iret stack frame)
         push rcx                  // Push userspace return pointer
     ",
 
@@ -113,8 +116,8 @@ function!(syscall_instruction => {
         pop rcx                 // Pop userspace return pointer
         add rsp, 8              // Pop fake userspace CS
         pop r11                 // Pop rflags
-        pop QWORD PTR gs:[0x08] // Pop userspace stack pointer
-        mov rsp, gs:[0x08]      // Restore userspace stack pointer
+        pop QWORD PTR gs:[{sp}] // Pop userspace stack pointer
+        mov rsp, gs:[{sp}]      // Restore userspace stack pointer
         swapgs                  // Restore gs from TSS to user data
         sysretq                 // Return into userspace; RCX=>RIP,R11=>RFLAGS
 
@@ -125,8 +128,16 @@ function!(syscall_instruction => {
         xor r11, r11
         swapgs
         iretq
-    ",
-});
+    "),
+
+    sp = const(offset_of!(gdt::ProcessorControlRegion, user_rsp_tmp)),
+    ksp = const(offset_of!(gdt::ProcessorControlRegion, tss) + offset_of!(TaskStateSegment, rsp)),
+    ss_sel = const(SegmentSelector::new(gdt::GDT_USER_DATA as u16, x86::Ring::Ring3).bits()),
+    cs_sel = const(SegmentSelector::new(gdt::GDT_USER_CODE as u16, x86::Ring::Ring3).bits()),
+
+    options(noreturn),
+    );
+}
 
 interrupt_stack!(syscall, |stack| {
     with_interrupt_stack!(|stack| {
@@ -150,7 +161,9 @@ interrupt_stack!(syscall, |stack| {
     })
 });
 
-function!(clone_ret => {
+#[naked]
+pub unsafe extern "C" fn clone_ret() {
+    asm!(concat!(
     // The address of this instruction is injected by `clone` in process.rs, on
     // top of the stack syscall->inner in this file, which is done using the rbp
     // register we save there.
@@ -165,4 +178,5 @@ function!(clone_ret => {
     "pop rbp\n",
     // ...and we return to the address at the top of the stack
     "ret\n",
-});
+    ), options(noreturn));
+}
-- 
GitLab