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}