• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Architecture-specific syscall code.
2 //!
3 //! `rustix` has inline assembly sequences using `asm!`, but that requires
4 //! nightly Rust, so it also has out-of-line ("outline") assembly sequences
5 //! in .s files. And 32-bit x86 is special (see comments below).
6 //!
7 //! This module also has a `choose` submodule which chooses a scheme and is
8 //! what most of the `rustix` syscalls use.
9 //!
10 //! # Safety
11 //!
12 //! This contains the inline `asm` statements performing the syscall
13 //! instructions and FFI declarations declaring the out-of-line ("outline")
14 //! syscall instructions.
15 
16 #![allow(unsafe_code)]
17 #![cfg_attr(not(feature = "all-apis"), allow(unused_imports))]
18 // We'll use as many arguments as syscalls need.
19 #![allow(clippy::too_many_arguments)]
20 
21 // When inline asm is available, use it. Otherwise, use out-of-line asm. These
22 // functions always use the machine's syscall instruction, even when it isn't
23 // the fastest option available.
24 #[cfg_attr(asm, path = "inline/mod.rs")]
25 #[cfg_attr(not(asm), path = "outline/mod.rs")]
26 pub(in crate::backend) mod asm;
27 
28 // On most architectures, the architecture syscall instruction is fast, so use
29 // it directly.
30 #[cfg(any(
31     target_arch = "arm",
32     target_arch = "aarch64",
33     target_arch = "mips",
34     target_arch = "mips64",
35     target_arch = "powerpc64",
36     target_arch = "riscv64",
37     target_arch = "x86_64",
38 ))]
39 pub(in crate::backend) use self::asm as choose;
40 
41 // On 32-bit x86, use vDSO wrappers for all syscalls. We could use the
42 // architecture syscall instruction (`int 0x80`), but the vDSO kernel_vsyscall
43 // mechanism is much faster.
44 #[cfg(target_arch = "x86")]
45 pub(in crate::backend) use super::vdso_wrappers::x86_via_vdso as choose;
46 
47 // This would be the code for always using `int 0x80` on 32-bit x86.
48 //#[cfg(target_arch = "x86")]
49 //pub(in crate::backend) use self::asm as choose;
50 
51 // Macros for invoking system calls.
52 //
53 // These factor out:
54 //  - Calling `nr` on the syscall number to convert it into `SyscallNumber`.
55 //  - Calling `.into()` on each of the arguments to convert them into `ArgReg`.
56 //  - Qualifying the `syscall*` and `__NR_*` identifiers.
57 //  - Counting the number of arguments.
58 macro_rules! syscall {
59     ($nr:ident) => {
60         $crate::backend::arch::choose::syscall0($crate::backend::reg::nr(
61             linux_raw_sys::general::$nr,
62         ))
63     };
64 
65     ($nr:ident, $a0:expr) => {
66         $crate::backend::arch::choose::syscall1(
67             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
68             $a0.into(),
69         )
70     };
71 
72     ($nr:ident, $a0:expr, $a1:expr) => {
73         $crate::backend::arch::choose::syscall2(
74             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
75             $a0.into(),
76             $a1.into(),
77         )
78     };
79 
80     ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
81         $crate::backend::arch::choose::syscall3(
82             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
83             $a0.into(),
84             $a1.into(),
85             $a2.into(),
86         )
87     };
88 
89     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
90         $crate::backend::arch::choose::syscall4(
91             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
92             $a0.into(),
93             $a1.into(),
94             $a2.into(),
95             $a3.into(),
96         )
97     };
98 
99     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
100         $crate::backend::arch::choose::syscall5(
101             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
102             $a0.into(),
103             $a1.into(),
104             $a2.into(),
105             $a3.into(),
106             $a4.into(),
107         )
108     };
109 
110     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
111         $crate::backend::arch::choose::syscall6(
112             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
113             $a0.into(),
114             $a1.into(),
115             $a2.into(),
116             $a3.into(),
117             $a4.into(),
118             $a5.into(),
119         )
120     };
121 
122     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
123         $crate::backend::arch::choose::syscall7(
124             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
125             $a0.into(),
126             $a1.into(),
127             $a2.into(),
128             $a3.into(),
129             $a4.into(),
130             $a5.into(),
131             $a6.into(),
132         )
133     };
134 }
135 
136 macro_rules! syscall_readonly {
137     ($nr:ident) => {
138         $crate::backend::arch::choose::syscall0_readonly($crate::backend::reg::nr(
139             linux_raw_sys::general::$nr,
140         ))
141     };
142 
143     ($nr:ident, $a0:expr) => {
144         $crate::backend::arch::choose::syscall1_readonly(
145             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
146             $a0.into(),
147         )
148     };
149 
150     ($nr:ident, $a0:expr, $a1:expr) => {
151         $crate::backend::arch::choose::syscall2_readonly(
152             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
153             $a0.into(),
154             $a1.into(),
155         )
156     };
157 
158     ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
159         $crate::backend::arch::choose::syscall3_readonly(
160             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
161             $a0.into(),
162             $a1.into(),
163             $a2.into(),
164         )
165     };
166 
167     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
168         $crate::backend::arch::choose::syscall4_readonly(
169             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
170             $a0.into(),
171             $a1.into(),
172             $a2.into(),
173             $a3.into(),
174         )
175     };
176 
177     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
178         $crate::backend::arch::choose::syscall5_readonly(
179             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
180             $a0.into(),
181             $a1.into(),
182             $a2.into(),
183             $a3.into(),
184             $a4.into(),
185         )
186     };
187 
188     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
189         $crate::backend::arch::choose::syscall6_readonly(
190             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
191             $a0.into(),
192             $a1.into(),
193             $a2.into(),
194             $a3.into(),
195             $a4.into(),
196             $a5.into(),
197         )
198     };
199 
200     ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
201         $crate::backend::arch::choose::syscall7_readonly(
202             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
203             $a0.into(),
204             $a1.into(),
205             $a2.into(),
206             $a3.into(),
207             $a4.into(),
208             $a5.into(),
209             $a6.into(),
210         )
211     };
212 }
213 
214 #[cfg(feature = "runtime")]
215 macro_rules! syscall_noreturn {
216     ($nr:ident, $a0:expr) => {
217         $crate::backend::arch::choose::syscall1_noreturn(
218             $crate::backend::reg::nr(linux_raw_sys::general::$nr),
219             $a0.into(),
220         )
221     };
222 }
223