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