polkavm_linux_raw/
arch_amd64_syscall.rs

1// These functions are based on the ones from `rustix`: https://github.com/bytecodealliance/rustix/blob/2064196e201a574ffa5bc214a065cf6faffbe97c/src/backend/linux_raw/arch/inline/x86_64.rs
2
3use core::arch::asm;
4use core::ffi::c_long;
5use core::marker::PhantomData;
6
7#[cfg(target_pointer_width = "32")]
8compile_error!("x32 is not supported");
9
10#[repr(transparent)]
11#[derive(Copy, Clone)]
12pub struct SyscallArg<'a>(usize, PhantomData<&'a ()>);
13
14impl From<i32> for SyscallArg<'_> {
15    #[inline]
16    fn from(value: i32) -> Self {
17        SyscallArg(value as isize as usize, PhantomData)
18    }
19}
20
21impl From<i64> for SyscallArg<'_> {
22    #[inline]
23    fn from(value: i64) -> Self {
24        SyscallArg(value as isize as usize, PhantomData)
25    }
26}
27
28impl From<isize> for SyscallArg<'_> {
29    #[inline]
30    fn from(value: isize) -> Self {
31        SyscallArg(value as usize, PhantomData)
32    }
33}
34
35impl From<u32> for SyscallArg<'_> {
36    #[inline]
37    fn from(value: u32) -> Self {
38        SyscallArg(value as usize, PhantomData)
39    }
40}
41
42impl From<u64> for SyscallArg<'_> {
43    #[inline]
44    fn from(value: u64) -> Self {
45        SyscallArg(value as usize, PhantomData)
46    }
47}
48
49impl From<usize> for SyscallArg<'_> {
50    #[inline]
51    fn from(value: usize) -> Self {
52        SyscallArg(value, PhantomData)
53    }
54}
55
56impl<T> From<*const T> for SyscallArg<'_> {
57    #[inline]
58    fn from(value: *const T) -> Self {
59        SyscallArg(value as usize, PhantomData)
60    }
61}
62
63impl<T> From<*mut T> for SyscallArg<'_> {
64    #[inline]
65    fn from(value: *mut T) -> Self {
66        SyscallArg(value as usize, PhantomData)
67    }
68}
69
70impl<'a, T> From<&'a [T]> for SyscallArg<'a> {
71    #[inline]
72    fn from(value: &'a [T]) -> Self {
73        SyscallArg::from(value.as_ptr())
74    }
75}
76
77impl<'a, T, const N: usize> From<&'a [T; N]> for SyscallArg<'a> {
78    #[inline]
79    fn from(value: &'a [T; N]) -> Self {
80        SyscallArg::from(value.as_ptr())
81    }
82}
83
84impl<'a, T> From<&'a mut [T]> for SyscallArg<'a> {
85    #[inline]
86    fn from(value: &'a mut [T]) -> Self {
87        SyscallArg::from(value.as_mut_ptr())
88    }
89}
90
91impl<'a> From<crate::FdRef<'a>> for SyscallArg<'a> {
92    #[inline]
93    fn from(value: crate::FdRef<'a>) -> Self {
94        SyscallArg(value.raw() as isize as usize, PhantomData)
95    }
96}
97
98impl<'a> From<Option<crate::FdRef<'a>>> for SyscallArg<'a> {
99    #[inline]
100    fn from(value: Option<crate::FdRef<'a>>) -> Self {
101        SyscallArg(value.map_or(-1, |fd| fd.raw()) as isize as usize, PhantomData)
102    }
103}
104
105impl<'a> From<&'a crate::Fd> for SyscallArg<'a> {
106    #[inline]
107    fn from(value: &'a crate::Fd) -> Self {
108        SyscallArg(value.raw() as isize as usize, PhantomData)
109    }
110}
111
112impl<'a> From<&'a core::ffi::CStr> for SyscallArg<'a> {
113    #[inline]
114    fn from(value: &'a core::ffi::CStr) -> Self {
115        SyscallArg(value.as_ptr() as usize, PhantomData)
116    }
117}
118
119#[inline]
120pub unsafe fn syscall0_readonly(nr: c_long) -> c_long {
121    let r0;
122    asm!(
123        "syscall",
124        inlateout("rax") nr => r0,
125        lateout("rcx") _,
126        lateout("r11") _,
127        options(nostack, preserves_flags, readonly)
128    );
129    r0
130}
131
132#[inline]
133pub unsafe fn syscall1(nr: c_long, a0: SyscallArg) -> c_long {
134    let r0;
135    asm!(
136        "syscall",
137        inlateout("rax") nr => r0,
138        in("rdi") a0.0,
139        lateout("rcx") _,
140        lateout("r11") _,
141        options(nostack, preserves_flags)
142    );
143    r0
144}
145
146#[inline]
147pub unsafe fn syscall1_readonly(nr: c_long, a0: SyscallArg) -> c_long {
148    let r0;
149    asm!(
150        "syscall",
151        inlateout("rax") nr => r0,
152        in("rdi") a0.0,
153        lateout("rcx") _,
154        lateout("r11") _,
155        options(nostack, preserves_flags, readonly)
156    );
157    r0
158}
159
160#[inline]
161pub unsafe fn syscall1_noreturn(nr: c_long, a0: SyscallArg) -> ! {
162    asm!(
163        "syscall",
164        in("rax") nr,
165        in("rdi") a0.0,
166        options(noreturn)
167    )
168}
169
170#[inline]
171pub unsafe fn syscall2(nr: c_long, a0: SyscallArg, a1: SyscallArg) -> c_long {
172    let r0;
173    asm!(
174        "syscall",
175        inlateout("rax") nr => r0,
176        in("rdi") a0.0,
177        in("rsi") a1.0,
178        lateout("rcx") _,
179        lateout("r11") _,
180        options(nostack, preserves_flags)
181    );
182    r0
183}
184
185#[inline]
186pub unsafe fn syscall2_readonly(nr: c_long, a0: SyscallArg, a1: SyscallArg) -> c_long {
187    let r0;
188    asm!(
189        "syscall",
190        inlateout("rax") nr => r0,
191        in("rdi") a0.0,
192        in("rsi") a1.0,
193        lateout("rcx") _,
194        lateout("r11") _,
195        options(nostack, preserves_flags, readonly)
196    );
197    r0
198}
199
200#[inline]
201pub unsafe fn syscall3(nr: c_long, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg) -> c_long {
202    let r0;
203    asm!(
204        "syscall",
205        inlateout("rax") nr => r0,
206        in("rdi") a0.0,
207        in("rsi") a1.0,
208        in("rdx") a2.0,
209        lateout("rcx") _,
210        lateout("r11") _,
211        options(nostack, preserves_flags)
212    );
213    r0
214}
215
216#[inline]
217pub unsafe fn syscall3_readonly(nr: u64, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg) -> c_long {
218    let r0;
219    asm!(
220        "syscall",
221        inlateout("rax") nr => r0,
222        in("rdi") a0.0,
223        in("rsi") a1.0,
224        in("rdx") a2.0,
225        lateout("rcx") _,
226        lateout("r11") _,
227        options(nostack, preserves_flags, readonly)
228    );
229    r0
230}
231
232#[inline]
233pub unsafe fn syscall4(nr: c_long, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg, a3: SyscallArg) -> c_long {
234    let r0;
235    asm!(
236        "syscall",
237        inlateout("rax") nr => r0,
238        in("rdi") a0.0,
239        in("rsi") a1.0,
240        in("rdx") a2.0,
241        in("r10") a3.0,
242        lateout("rcx") _,
243        lateout("r11") _,
244        options(nostack, preserves_flags)
245    );
246    r0
247}
248
249#[inline]
250pub unsafe fn syscall4_readonly(nr: c_long, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg, a3: SyscallArg) -> c_long {
251    let r0;
252    asm!(
253        "syscall",
254        inlateout("rax") nr => r0,
255        in("rdi") a0.0,
256        in("rsi") a1.0,
257        in("rdx") a2.0,
258        in("r10") a3.0,
259        lateout("rcx") _,
260        lateout("r11") _,
261        options(nostack, preserves_flags, readonly)
262    );
263    r0
264}
265
266#[inline]
267pub unsafe fn syscall5(nr: c_long, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg, a3: SyscallArg, a4: SyscallArg) -> c_long {
268    let r0;
269    asm!(
270        "syscall",
271        inlateout("rax") nr => r0,
272        in("rdi") a0.0,
273        in("rsi") a1.0,
274        in("rdx") a2.0,
275        in("r10") a3.0,
276        in("r8") a4.0,
277        lateout("rcx") _,
278        lateout("r11") _,
279        options(nostack, preserves_flags)
280    );
281    r0
282}
283
284#[inline]
285pub unsafe fn syscall5_readonly(nr: c_long, a0: SyscallArg, a1: SyscallArg, a2: SyscallArg, a3: SyscallArg, a4: SyscallArg) -> c_long {
286    let r0;
287    asm!(
288        "syscall",
289        inlateout("rax") nr => r0,
290        in("rdi") a0.0,
291        in("rsi") a1.0,
292        in("rdx") a2.0,
293        in("r10") a3.0,
294        in("r8") a4.0,
295        lateout("rcx") _,
296        lateout("r11") _,
297        options(nostack, preserves_flags, readonly)
298    );
299    r0
300}
301
302#[inline]
303pub unsafe fn syscall6(
304    nr: c_long,
305    a0: SyscallArg,
306    a1: SyscallArg,
307    a2: SyscallArg,
308    a3: SyscallArg,
309    a4: SyscallArg,
310    a5: SyscallArg,
311) -> c_long {
312    let r0;
313    asm!(
314        "syscall",
315        inlateout("rax") nr => r0,
316        in("rdi") a0.0,
317        in("rsi") a1.0,
318        in("rdx") a2.0,
319        in("r10") a3.0,
320        in("r8") a4.0,
321        in("r9") a5.0,
322        lateout("rcx") _,
323        lateout("r11") _,
324        options(nostack, preserves_flags)
325    );
326    r0
327}
328
329#[inline]
330pub unsafe fn syscall6_readonly(
331    nr: c_long,
332    a0: SyscallArg,
333    a1: SyscallArg,
334    a2: SyscallArg,
335    a3: SyscallArg,
336    a4: SyscallArg,
337    a5: SyscallArg,
338) -> c_long {
339    let r0;
340    asm!(
341        "syscall",
342        inlateout("rax") nr => r0,
343        in("rdi") a0.0,
344        in("rsi") a1.0,
345        in("rdx") a2.0,
346        in("r10") a3.0,
347        in("r8") a4.0,
348        in("r9") a5.0,
349        lateout("rcx") _,
350        lateout("r11") _,
351        options(nostack, preserves_flags, readonly)
352    );
353    r0
354}