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}