aboutsummaryrefslogtreecommitdiff
path: root/vendor/rustix/src/backend/linux_raw/arch/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/arch/mod.rs')
-rw-r--r--vendor/rustix/src/backend/linux_raw/arch/mod.rs317
1 files changed, 317 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/arch/mod.rs b/vendor/rustix/src/backend/linux_raw/arch/mod.rs
new file mode 100644
index 0000000..ac9e25f
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/arch/mod.rs
@@ -0,0 +1,317 @@
+//! Architecture-specific syscall code.
+//!
+//! This module also has a `choose` submodule which chooses a scheme and is
+//! what most of the `rustix` syscalls use.
+//!
+//! Compilers should really have intrinsics for making system calls. They're
+//! much like regular calls, with custom calling conventions, and calling
+//! conventions are otherwise the compiler's job. But for now, use inline asm.
+//!
+//! The calling conventions for Linux syscalls are [documented here].
+//!
+//! [documented here]: https://man7.org/linux/man-pages/man2/syscall.2.html
+//!
+//! # Safety
+//!
+//! This contains the inline `asm` statements performing the syscall
+//! instructions.
+
+#![allow(unsafe_code)]
+#![cfg_attr(not(feature = "all-apis"), allow(unused_imports))]
+// We'll use as many arguments as syscalls need.
+#![allow(clippy::too_many_arguments)]
+
+// These functions always use the machine's syscall instruction, even when it
+// isn't the fastest option available.
+#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
+#[cfg_attr(all(target_arch = "arm", not(thumb_mode)), path = "arm.rs")]
+#[cfg_attr(all(target_arch = "arm", thumb_mode), path = "thumb.rs")]
+#[cfg_attr(target_arch = "mips", path = "mips.rs")]
+#[cfg_attr(target_arch = "mips32r6", path = "mips32r6.rs")]
+#[cfg_attr(target_arch = "mips64", path = "mips64.rs")]
+#[cfg_attr(target_arch = "mips64r6", path = "mips64r6.rs")]
+#[cfg_attr(target_arch = "powerpc64", path = "powerpc64.rs")]
+#[cfg_attr(target_arch = "riscv64", path = "riscv64.rs")]
+#[cfg_attr(target_arch = "x86", path = "x86.rs")]
+#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
+pub(in crate::backend) mod asm;
+
+// On most architectures, the architecture syscall instruction is fast, so use
+// it directly.
+#[cfg(any(
+ target_arch = "arm",
+ target_arch = "aarch64",
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+))]
+pub(in crate::backend) use self::asm as choose;
+
+// On 32-bit x86, use vDSO wrappers for all syscalls. We could use the
+// architecture syscall instruction (`int 0x80`), but the vDSO kernel_vsyscall
+// mechanism is much faster.
+#[cfg(target_arch = "x86")]
+pub(in crate::backend) use super::vdso_wrappers::x86_via_vdso as choose;
+
+// This would be the code for always using `int 0x80` on 32-bit x86.
+//#[cfg(target_arch = "x86")]
+//pub(in crate::backend) use self::asm as choose;
+
+// Macros for invoking system calls.
+//
+// These factor out:
+// - Calling `nr` on the syscall number to convert it into `SyscallNumber`.
+// - Calling `.into()` on each of the arguments to convert them into `ArgReg`.
+// - Qualifying the `syscall*` and `__NR_*` identifiers.
+// - Counting the number of arguments.
+macro_rules! syscall {
+ ($nr:ident) => {
+ $crate::backend::arch::choose::syscall0($crate::backend::reg::nr(
+ linux_raw_sys::general::$nr,
+ ))
+ };
+
+ ($nr:ident, $a0:expr) => {
+ $crate::backend::arch::choose::syscall1(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr) => {
+ $crate::backend::arch::choose::syscall2(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
+ $crate::backend::arch::choose::syscall3(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
+ $crate::backend::arch::choose::syscall4(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
+ $crate::backend::arch::choose::syscall5(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
+ $crate::backend::arch::choose::syscall6(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
+ $crate::backend::arch::choose::syscall7(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ $a6.into(),
+ )
+ };
+}
+
+// Macro to invoke a syscall that always uses direct assembly, rather than the
+// vDSO. Useful when still finding the vDSO.
+#[allow(unused_macros)]
+macro_rules! syscall_always_asm {
+ ($nr:ident) => {
+ $crate::backend::arch::asm::syscall0($crate::backend::reg::nr(linux_raw_sys::general::$nr))
+ };
+
+ ($nr:ident, $a0:expr) => {
+ $crate::backend::arch::asm::syscall1(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr) => {
+ $crate::backend::arch::asm::syscall2(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
+ $crate::backend::arch::asm::syscall3(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
+ $crate::backend::arch::asm::syscall4(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
+ $crate::backend::arch::asm::syscall5(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
+ $crate::backend::arch::asm::syscall6(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
+ $crate::backend::arch::asm::syscall7(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ $a6.into(),
+ )
+ };
+}
+
+/// Like `syscall`, but adds the `readonly` attribute to the inline asm, which
+/// indicates that the syscall does not mutate any memory.
+macro_rules! syscall_readonly {
+ ($nr:ident) => {
+ $crate::backend::arch::choose::syscall0_readonly($crate::backend::reg::nr(
+ linux_raw_sys::general::$nr,
+ ))
+ };
+
+ ($nr:ident, $a0:expr) => {
+ $crate::backend::arch::choose::syscall1_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr) => {
+ $crate::backend::arch::choose::syscall2_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
+ $crate::backend::arch::choose::syscall3_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
+ $crate::backend::arch::choose::syscall4_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
+ $crate::backend::arch::choose::syscall5_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
+ $crate::backend::arch::choose::syscall6_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ )
+ };
+
+ ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
+ $crate::backend::arch::choose::syscall7_readonly(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ $a1.into(),
+ $a2.into(),
+ $a3.into(),
+ $a4.into(),
+ $a5.into(),
+ $a6.into(),
+ )
+ };
+}
+
+/// Like `syscall`, but indicates that the syscall does not return.
+#[cfg(feature = "runtime")]
+macro_rules! syscall_noreturn {
+ ($nr:ident, $a0:expr) => {
+ $crate::backend::arch::choose::syscall1_noreturn(
+ $crate::backend::reg::nr(linux_raw_sys::general::$nr),
+ $a0.into(),
+ )
+ };
+}