syscalls/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/// Issues a raw system call with 0 arguments.
17///
18/// # Safety
19///
20/// Running a system call is inherently unsafe. It is the caller's
21/// responsibility to ensure safety.
22#[inline]
23pub unsafe fn syscall0(n: usize) -> usize {
24 let mut ret: usize;
25 asm!(
26 "syscall",
27 inlateout("rax") n => ret,
28 out("rcx") _, // rcx is used to store old rip
29 out("r11") _, // r11 is used to store old rflags
30 options(nostack, preserves_flags)
31 );
32 ret
33}
34
35/// Issues a raw system call with 1 argument.
36///
37/// # Safety
38///
39/// Running a system call is inherently unsafe. It is the caller's
40/// responsibility to ensure safety.
41#[inline]
42pub unsafe fn syscall1(n: usize, arg1: usize) -> usize {
43 let mut ret: usize;
44 asm!(
45 "syscall",
46 inlateout("rax") n => ret,
47 in("rdi") arg1,
48 out("rcx") _, // rcx is used to store old rip
49 out("r11") _, // r11 is used to store old rflags
50 options(nostack, preserves_flags)
51 );
52 ret
53}
54
55/// Issues a raw system call with 2 arguments.
56///
57/// # Safety
58///
59/// Running a system call is inherently unsafe. It is the caller's
60/// responsibility to ensure safety.
61#[inline]
62pub unsafe fn syscall2(n: usize, arg1: usize, arg2: usize) -> usize {
63 let mut ret: usize;
64 asm!(
65 "syscall",
66 inlateout("rax") n => ret,
67 in("rdi") arg1,
68 in("rsi") arg2,
69 out("rcx") _, // rcx is used to store old rip
70 out("r11") _, // r11 is used to store old rflags
71 options(nostack, preserves_flags)
72 );
73 ret
74}
75
76/// Issues a raw system call with 3 arguments.
77///
78/// # Safety
79///
80/// Running a system call is inherently unsafe. It is the caller's
81/// responsibility to ensure safety.
82#[inline]
83pub unsafe fn syscall3(
84 n: usize,
85 arg1: usize,
86 arg2: usize,
87 arg3: usize,
88) -> usize {
89 let mut ret: usize;
90 asm!(
91 "syscall",
92 inlateout("rax") n => ret,
93 in("rdi") arg1,
94 in("rsi") arg2,
95 in("rdx") arg3,
96 out("rcx") _, // rcx is used to store old rip
97 out("r11") _, // r11 is used to store old rflags
98 options(nostack, preserves_flags)
99 );
100 ret
101}
102
103/// Issues a raw system call with 4 arguments.
104///
105/// # Safety
106///
107/// Running a system call is inherently unsafe. It is the caller's
108/// responsibility to ensure safety.
109#[inline]
110pub unsafe fn syscall4(
111 n: usize,
112 arg1: usize,
113 arg2: usize,
114 arg3: usize,
115 arg4: usize,
116) -> usize {
117 let mut ret: usize;
118 asm!(
119 "syscall",
120 inlateout("rax") n => ret,
121 in("rdi") arg1,
122 in("rsi") arg2,
123 in("rdx") arg3,
124 in("r10") arg4,
125 out("rcx") _, // rcx is used to store old rip
126 out("r11") _, // r11 is used to store old rflags
127 options(nostack, preserves_flags)
128 );
129 ret
130}
131
132/// Issues a raw system call with 5 arguments.
133///
134/// # Safety
135///
136/// Running a system call is inherently unsafe. It is the caller's
137/// responsibility to ensure safety.
138#[inline]
139pub unsafe fn syscall5(
140 n: usize,
141 arg1: usize,
142 arg2: usize,
143 arg3: usize,
144 arg4: usize,
145 arg5: usize,
146) -> usize {
147 let mut ret: usize;
148 asm!(
149 "syscall",
150 inlateout("rax") n => ret,
151 in("rdi") arg1,
152 in("rsi") arg2,
153 in("rdx") arg3,
154 in("r10") arg4,
155 in("r8") arg5,
156 out("rcx") _, // rcx is used to store old rip
157 out("r11") _, // r11 is used to store old rflags
158 options(nostack, preserves_flags)
159 );
160 ret
161}
162
163/// Issues a raw system call with 6 arguments.
164///
165/// # Safety
166///
167/// Running a system call is inherently unsafe. It is the caller's
168/// responsibility to ensure safety.
169#[inline]
170pub unsafe fn syscall6(
171 n: usize,
172 arg1: usize,
173 arg2: usize,
174 arg3: usize,
175 arg4: usize,
176 arg5: usize,
177 arg6: usize,
178) -> usize {
179 let mut ret: usize;
180 asm!(
181 "syscall",
182 inlateout("rax") n => ret,
183 in("rdi") arg1,
184 in("rsi") arg2,
185 in("rdx") arg3,
186 in("r10") arg4,
187 in("r8") arg5,
188 in("r9") arg6,
189 out("rcx") _, // rcx is used to store old rip
190 out("r11") _, // r11 is used to store old rflags
191 options(nostack, preserves_flags)
192 );
193 ret
194}