r_linux/syscall/arch/
mod.rs

1//! Architecture Dependent Definitions
2//!
3//! Depending on the architecture, the linux ABI can differ greatly. This
4//! module contains the architecture dependent definitions and entry-points
5//! for each supported architecture.
6//!
7//! All code for all architectures is always available. Use the `native`
8//! module to get a link to the architecture native to your compilation.
9//! Alternatively, use `cfg(target_arch = "xyz")` to test for the architecture
10//! of your choice.
11
12// Target Architecture
13//
14// We need architecture-dependent assembly to invoke system calls. To avoid
15// spurious linker errors in dependent crates, we check for supported
16// architectures here and error out right away.
17#[cfg(not(any(
18    target_arch = "x86",
19    target_arch = "x86_64",
20)))]
21compile_error!("Target architecture not supported.");
22
23pub mod x86;
24pub mod x86_64;
25
26/// Native Architecture
27///
28/// This module re-exports the symbols of the architecture native to this
29/// compilation (i.e., the target architecture). That is, rather than gating
30/// your access to symbols in the `arch::<id>` module via
31/// `cfg(target_arch = "id")`, you can directly use `arch::native` and rely on
32/// compile-time verification that the symbols are available.
33///
34/// Note that your code will become architecture-dependent when you use this
35/// re-export, as it can and will expose differences between the ABIs of the
36/// linux kernel architecture. However, in a lot of cases this might be what
37/// you want, and it also can simplify bootstrapping applications quite a bit.
38///
39/// Note that for documentation reasons, this module shows the symbols of the
40/// `x86_64` architecture. However, depending on what target you compile for,
41/// other symbols will be exported.
42#[cfg(doctest)]
43pub mod native {
44    pub use super::x86_64::*;
45}
46
47#[cfg(all(not(doctest), target_arch = "x86"))]
48pub mod native {
49    pub use super::x86::*;
50}
51
52#[cfg(all(not(doctest), target_arch = "x86_64"))]
53pub mod native {
54    pub use super::x86_64::*;
55}
56
57#[cfg(test)]
58mod test {
59    use super::*;
60
61    #[test]
62    fn native_check() {
63        //
64        // Verify the `native` module is available and links to an
65        // actual architecture.
66        //
67
68        assert_ne!(native::nr::EXIT, 0);
69    }
70
71    #[test]
72    fn arch_availability() {
73        //
74        // Verify all architectures are always compiled in and accessible. We
75        // simply check for their hard-coded `nr::EXIT` symbols here.
76        //
77
78        assert_eq!(x86::nr::EXIT, 1);
79        assert_eq!(x86_64::nr::EXIT, 60);
80    }
81
82    #[test]
83    fn syscall_check() {
84        //
85        // Verify the `syscall0` to `syscall6` symbols are always available on
86        // the native architectures with the same prototype. Note that
87        // non-native prototypes are not available, since it would be non-sense
88        // to compile their assembly.
89        //
90
91        let s0: unsafe fn(
92            usize,
93        ) -> usize = native::syscall::syscall0;
94        let s1: unsafe fn(
95            usize,
96            usize,
97        ) -> usize = native::syscall::syscall1;
98        let s2: unsafe fn(
99            usize,
100            usize,
101            usize,
102        ) -> usize = native::syscall::syscall2;
103        let s3: unsafe fn(
104            usize,
105            usize,
106            usize,
107            usize,
108        ) -> usize = native::syscall::syscall3;
109        let s4: unsafe fn(
110            usize,
111            usize,
112            usize,
113            usize,
114            usize,
115        ) -> usize = native::syscall::syscall4;
116        let s5: unsafe fn(
117            usize,
118            usize,
119            usize,
120            usize,
121            usize,
122            usize,
123        ) -> usize = native::syscall::syscall5;
124        let s6: unsafe fn(
125            usize,
126            usize,
127            usize,
128            usize,
129            usize,
130            usize,
131            usize,
132        ) -> usize = native::syscall::syscall6;
133
134        assert_ne!(s0 as *const () as usize, 0);
135        assert_ne!(s1 as *const () as usize, 0);
136        assert_ne!(s2 as *const () as usize, 0);
137        assert_ne!(s3 as *const () as usize, 0);
138        assert_ne!(s4 as *const () as usize, 0);
139        assert_ne!(s5 as *const () as usize, 0);
140        assert_ne!(s6 as *const () as usize, 0);
141    }
142}