safa_api/syscalls/
mod.rs

1//! This module exposes SafaOS's syscalls and their rust counterparts
2
3#[cfg(not(feature = "rustc-dep-of-std"))]
4extern crate alloc;
5use core::arch::asm;
6pub use safa_abi::syscalls::SyscallTable as SyscallNum;
7
8macro_rules! err_from_u16 {
9    ($result:expr) => {
10        $result.into_result()
11    };
12    ($result:expr, $ok:expr) => {
13        err_from_u16!($result).map(|()| $ok)
14    };
15}
16
17pub(crate) use err_from_u16;
18
19#[doc(hidden)]
20#[inline(always)]
21pub fn syscall0<const NUM: u16>() -> SyscallResult {
22    let result: u16;
23    unsafe {
24        #[cfg(target_arch = "x86_64")]
25        asm!(
26            "int 0x80",
27            in("rax") NUM as usize,
28            lateout("rax") result,
29        );
30        #[cfg(target_arch = "aarch64")]
31        asm!(
32            "svc #{num}",
33            num = const NUM,
34            lateout("x0") result
35        );
36        core::mem::transmute(result)
37    }
38}
39
40#[doc(hidden)]
41#[inline(always)]
42pub fn syscall1<const NUM: u16>(arg1: usize) -> SyscallResult {
43    let result: u16;
44    unsafe {
45        #[cfg(target_arch = "x86_64")]
46        asm!(
47            "int 0x80",
48            in("rax") NUM as usize,
49            in("rdi") arg1,
50            lateout("rax") result,
51        );
52        #[cfg(target_arch = "aarch64")]
53        asm!(
54            "svc #{num}",
55            num = const NUM,
56            in("x0") arg1,
57            lateout("x0") result
58        );
59        core::mem::transmute(result)
60    }
61}
62
63#[doc(hidden)]
64#[inline(always)]
65pub fn syscall2<const NUM: u16>(arg1: usize, arg2: usize) -> SyscallResult {
66    let result: u16;
67    unsafe {
68        #[cfg(target_arch = "x86_64")]
69        asm!(
70            "int 0x80",
71            in("rax") NUM as usize,
72            in("rdi") arg1,
73            in("rsi") arg2,
74            lateout("rax") result,
75        );
76        #[cfg(target_arch = "aarch64")]
77        asm!(
78            "svc #{num}",
79            num = const NUM,
80            in("x0") arg1,
81            in("x1") arg2,
82            lateout("x0") result
83        );
84        core::mem::transmute(result)
85    }
86}
87
88#[doc(hidden)]
89#[inline(always)]
90pub fn syscall3<const NUM: u16>(arg1: usize, arg2: usize, arg3: usize) -> SyscallResult {
91    let result: u16;
92    unsafe {
93        #[cfg(target_arch = "x86_64")]
94        asm!(
95            "int 0x80",
96            in("rax") NUM as usize,
97            in("rdi") arg1,
98            in("rsi") arg2,
99            in("rdx") arg3,
100            lateout("rax") result,
101        );
102        #[cfg(target_arch = "aarch64")]
103        asm!(
104            "svc #{num}",
105            num = const NUM,
106            in("x0") arg1,
107            in("x1") arg2,
108            in("x2") arg3,
109            lateout("x0") result
110        );
111        core::mem::transmute(result)
112    }
113}
114
115#[doc(hidden)]
116#[inline(always)]
117pub fn syscall4<const NUM: u16>(
118    arg1: usize,
119    arg2: usize,
120    arg3: usize,
121    arg4: usize,
122) -> SyscallResult {
123    let result: u16;
124    unsafe {
125        #[cfg(target_arch = "x86_64")]
126        asm!(
127            "int 0x80",
128            in("rax") NUM as usize,
129            in("rdi") arg1,
130            in("rsi") arg2,
131            in("rdx") arg3,
132            in("rcx") arg4,
133            lateout("rax") result,
134        );
135
136        #[cfg(target_arch = "aarch64")]
137        asm!(
138            "svc #{num}",
139            num = const NUM,
140            in("x0") arg1,
141            in("x1") arg2,
142            in("x2") arg3,
143            in("x3") arg4,
144            lateout("x0") result
145        );
146        core::mem::transmute(result)
147    }
148}
149
150#[doc(hidden)]
151#[inline(always)]
152pub fn syscall5<const NUM: u16>(
153    arg1: usize,
154    arg2: usize,
155    arg3: usize,
156    arg4: usize,
157    arg5: usize,
158) -> SyscallResult {
159    let result: u16;
160    unsafe {
161        #[cfg(target_arch = "x86_64")]
162        asm!(
163            "int 0x80",
164            in("rax") NUM as usize,
165            in("rdi") arg1,
166            in("rsi") arg2,
167            in("rdx") arg3,
168            in("rcx") arg4,
169            in("r8") arg5,
170            lateout("rax") result,
171        );
172        #[cfg(target_arch = "aarch64")]
173        asm!(
174            "svc #{num}",
175            num = const NUM,
176            in("x0") arg1,
177            in("x1") arg2,
178            in("x2") arg3,
179            in("x3") arg4,
180            in("x4") arg5,
181            lateout("x0") result
182        );
183        core::mem::transmute(result)
184    }
185}
186
187/// Invokes a syscall with the given number and arguments
188/// Number must be of type [`SyscallNum`]
189/// Arguments must be of type [`usize`]
190/// returns a [`SyscallResult`]
191macro_rules! syscall {
192    ($num: path $(,)?) => {
193        $crate::syscalls::syscall0::<{ $num as u16 }>()
194    };
195    ($num: path, $arg1: expr $(,)?) => {
196        $crate::syscalls::syscall1::<{ $num as u16 }>($arg1)
197    };
198    ($num: path, $arg1: expr, $arg2: expr $(,)?) => {
199        $crate::syscalls::syscall2::<{ $num as u16 }>($arg1, $arg2)
200    };
201    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr $(,)?) => {
202        $crate::syscalls::syscall3::<{ $num as u16 }>($arg1, $arg2, $arg3)
203    };
204    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr $(,)?) => {
205        $crate::syscalls::syscall4::<{ $num as u16 }>($arg1, $arg2, $arg3, $arg4)
206    };
207    ($num: path, $arg1: expr, $arg2: expr, $arg3: expr, $arg4: expr, $arg5: expr $(,)?) => {
208        $crate::syscalls::syscall5::<{ $num as u16 }>($arg1, $arg2, $arg3, $arg4, $arg5)
209    };
210}
211
212pub(crate) use syscall;
213
214macro_rules! define_syscall {
215    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) unreachable }) => {
216        $(#[$attrss])*
217        #[cfg_attr(
218            not(any(feature = "std", feature = "rustc-dep-of-std")),
219            unsafe(no_mangle)
220        )]
221        #[inline(always)]
222        pub extern "C" fn $name($($arg: $ty),*) -> ! {
223            #[allow(unused_imports)]
224            use $crate::syscalls::types::IntoSyscallArg;
225            _ = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
226            unreachable!()
227        }
228    };
229    ($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident : $ty:ty),*) }) => {
230        $(#[$attrss])*
231        #[cfg_attr(
232            not(any(feature = "std", feature = "rustc-dep-of-std")),
233            unsafe(no_mangle)
234        )]
235        #[inline(always)]
236        pub extern "C" fn $name($($arg: $ty),*) -> $crate::syscalls::types::SyscallResult {
237            #[allow(unused_imports)]
238            use $crate::syscalls::types::IntoSyscallArg;
239            let result = $crate::syscalls::syscall!($num, $( $arg.into_syscall_arg() ),*);
240            result
241        }
242    };
243    {$($num:path => { $(#[$attrss:meta])* $name:ident ($($arg:ident: $ty:ty),*) $($modifier:tt)* }),* $(,)?} => {
244        $(define_syscall!($num => { $(#[$attrss])* $name($($arg: $ty),*) $($modifier)* });)*
245    };
246}
247
248pub(crate) use define_syscall;
249
250/// FS Operations related syscalls (that takes a path) such as create, remove, open, rename and etc
251pub mod fs;
252/// I/O Operations related syscalls (that takes a resource) such as read, write, truncate, etc
253pub mod io;
254/// Syscalls and operations that don't fall into a specific category
255pub mod misc;
256/// (SysP) Process related syscalls and operations
257pub mod process;
258/// Syscalls and operations related to the current process
259pub mod process_misc;
260/// (SysR) Resources related syscalls and operations such as destroying resources, duplicating them, etc
261pub mod resources;
262/// (SysT) Thread related syscalls and operations
263pub mod thread;
264
265use types::SyscallResult;
266/// Contains documentation-only types for syscall arguments
267pub mod types;