rawsys_linux/syscall/
x86_64.rs

1// On x86-64, the following registers are used for args 1-6:
2// arg1: %rdi
3// arg2: %rsi
4// arg3: %rdx
5// arg4: %r10
6// arg5: %r8
7// arg6: %r9
8//
9// rax is used for both the syscall number and the syscall return value.
10//
11// rcx and r11 are always clobbered. syscalls can also modify memory. With the
12// `asm!()` macro, it is assumed that memory is clobbered unless the nomem
13// option is specified.
14use core::arch::asm;
15
16/// System call argument/return type for x86_64 (64-bit)
17pub type SyscallWord = u64;
18
19/// Issues a raw system call with 0 arguments.
20///
21/// # Safety
22///
23/// Running a system call is inherently unsafe. It is the caller's
24/// responsibility to ensure safety.
25#[inline]
26pub unsafe fn syscall0(n: SyscallWord) -> SyscallWord {
27    let mut ret: SyscallWord;
28    unsafe {
29        asm!(
30            "syscall",
31            inlateout("rax") n => ret,
32            out("rcx") _, // rcx is used to store old rip
33            out("r11") _, // r11 is used to store old rflags
34            options(nostack, preserves_flags)
35        );
36    }
37    ret
38}
39
40/// Issues a raw system call with 1 argument.
41///
42/// # Safety
43///
44/// Running a system call is inherently unsafe. It is the caller's
45/// responsibility to ensure safety.
46#[inline]
47pub unsafe fn syscall1(n: SyscallWord, arg1: SyscallWord) -> SyscallWord {
48    let mut ret: SyscallWord;
49    unsafe {
50        asm!(
51            "syscall",
52            inlateout("rax") n => ret,
53            in("rdi") arg1,
54            out("rcx") _, // rcx is used to store old rip
55            out("r11") _, // r11 is used to store old rflags
56            options(nostack, preserves_flags)
57        );
58    }
59    ret
60}
61
62/// Issues a raw system call with 2 arguments.
63///
64/// # Safety
65///
66/// Running a system call is inherently unsafe. It is the caller's
67/// responsibility to ensure safety.
68#[inline]
69pub unsafe fn syscall2(
70    n: SyscallWord,
71    arg1: SyscallWord,
72    arg2: SyscallWord,
73) -> SyscallWord {
74    let mut ret: SyscallWord;
75    unsafe {
76        asm!(
77            "syscall",
78            inlateout("rax") n => ret,
79            in("rdi") arg1,
80            in("rsi") arg2,
81            out("rcx") _, // rcx is used to store old rip
82            out("r11") _, // r11 is used to store old rflags
83            options(nostack, preserves_flags)
84        );
85    }
86    ret
87}
88
89/// Issues a raw system call with 3 arguments.
90///
91/// # Safety
92///
93/// Running a system call is inherently unsafe. It is the caller's
94/// responsibility to ensure safety.
95#[inline]
96pub unsafe fn syscall3(
97    n: SyscallWord,
98    arg1: SyscallWord,
99    arg2: SyscallWord,
100    arg3: SyscallWord,
101) -> SyscallWord {
102    let mut ret: SyscallWord;
103    unsafe {
104        asm!(
105            "syscall",
106            inlateout("rax") n => ret,
107            in("rdi") arg1,
108            in("rsi") arg2,
109            in("rdx") arg3,
110            out("rcx") _, // rcx is used to store old rip
111            out("r11") _, // r11 is used to store old rflags
112            options(nostack, preserves_flags)
113        );
114    }
115    ret
116}
117
118/// Issues a raw system call with 4 arguments.
119///
120/// # Safety
121///
122/// Running a system call is inherently unsafe. It is the caller's
123/// responsibility to ensure safety.
124#[inline]
125pub unsafe fn syscall4(
126    n: SyscallWord,
127    arg1: SyscallWord,
128    arg2: SyscallWord,
129    arg3: SyscallWord,
130    arg4: SyscallWord,
131) -> SyscallWord {
132    let mut ret: SyscallWord;
133    unsafe {
134        asm!(
135            "syscall",
136            inlateout("rax") n => ret,
137            in("rdi") arg1,
138            in("rsi") arg2,
139            in("rdx") arg3,
140            in("r10") arg4,
141            out("rcx") _, // rcx is used to store old rip
142            out("r11") _, // r11 is used to store old rflags
143            options(nostack, preserves_flags)
144        );
145    }
146    ret
147}
148
149/// Issues a raw system call with 5 arguments.
150///
151/// # Safety
152///
153/// Running a system call is inherently unsafe. It is the caller's
154/// responsibility to ensure safety.
155#[inline]
156pub unsafe fn syscall5(
157    n: SyscallWord,
158    arg1: SyscallWord,
159    arg2: SyscallWord,
160    arg3: SyscallWord,
161    arg4: SyscallWord,
162    arg5: SyscallWord,
163) -> SyscallWord {
164    let mut ret: SyscallWord;
165    unsafe {
166        asm!(
167            "syscall",
168            inlateout("rax") n => ret,
169            in("rdi") arg1,
170            in("rsi") arg2,
171            in("rdx") arg3,
172            in("r10") arg4,
173            in("r8")  arg5,
174            out("rcx") _, // rcx is used to store old rip
175            out("r11") _, // r11 is used to store old rflags
176            options(nostack, preserves_flags)
177        );
178    }
179    ret
180}
181
182/// Issues a raw system call with 6 arguments.
183///
184/// # Safety
185///
186/// Running a system call is inherently unsafe. It is the caller's
187/// responsibility to ensure safety.
188#[inline]
189pub unsafe fn syscall6(
190    n: SyscallWord,
191    arg1: SyscallWord,
192    arg2: SyscallWord,
193    arg3: SyscallWord,
194    arg4: SyscallWord,
195    arg5: SyscallWord,
196    arg6: SyscallWord,
197) -> SyscallWord {
198    let mut ret: SyscallWord;
199    unsafe {
200        asm!(
201            "syscall",
202            inlateout("rax") n => ret,
203            in("rdi") arg1,
204            in("rsi") arg2,
205            in("rdx") arg3,
206            in("r10") arg4,
207            in("r8")  arg5,
208            in("r9")  arg6,
209            out("rcx") _, // rcx is used to store old rip
210            out("r11") _, // r11 is used to store old rflags
211            options(nostack, preserves_flags)
212        );
213    }
214    ret
215}