]>
Commit | Line | Data |
---|---|---|
fe692bf9 FG |
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 | } |