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}