cpufeatures/
aarch64.rs
1#[macro_export]
10#[doc(hidden)]
11macro_rules! __unless_target_features {
12 ($($tf:tt),+ => $body:expr ) => {
13 {
14 #[cfg(not(all($(target_feature=$tf,)*)))]
15 $body
16
17 #[cfg(all($(target_feature=$tf,)*))]
18 true
19 }
20 };
21}
22
23#[cfg(any(target_os = "linux", target_os = "android"))]
25#[macro_export]
26#[doc(hidden)]
27macro_rules! __detect_target_features {
28 ($($tf:tt),+) => {{
29 let hwcaps = $crate::aarch64::getauxval_hwcap();
30 $($crate::check!(hwcaps, $tf) & )+ true
31 }};
32}
33
34#[cfg(any(target_os = "linux", target_os = "android"))]
36pub fn getauxval_hwcap() -> u64 {
37 unsafe { libc::getauxval(libc::AT_HWCAP) }
38}
39
40#[cfg(target_vendor = "apple")]
42#[macro_export]
43#[doc(hidden)]
44macro_rules! __detect_target_features {
45 ($($tf:tt),+) => {{
46 $($crate::check!($tf) & )+ true
47 }};
48}
49
50#[cfg(any(target_os = "linux", target_os = "android"))]
52macro_rules! __expand_check_macro {
53 ($(($name:tt, $hwcap:ident)),* $(,)?) => {
54 #[macro_export]
55 #[doc(hidden)]
56 macro_rules! check {
57 $(
58 ($hwcaps:expr, $name) => {
59 (($hwcaps & $crate::aarch64::hwcaps::$hwcap) != 0)
60 };
61 )*
62 }
63 };
64}
65
66#[cfg(any(target_os = "linux", target_os = "android"))]
68__expand_check_macro! {
69 ("aes", AES), ("dit", DIT), ("sha2", SHA2), ("sha3", SHA3), ("sm4", SM4), }
75
76#[cfg(any(target_os = "linux", target_os = "android"))]
84pub mod hwcaps {
85 use libc::c_ulong;
86
87 pub const AES: c_ulong = libc::HWCAP_AES | libc::HWCAP_PMULL;
88 pub const DIT: c_ulong = libc::HWCAP_DIT;
89 pub const SHA2: c_ulong = libc::HWCAP_SHA2;
90 pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512;
91 pub const SM4: c_ulong = libc::HWCAP_SM3 | libc::HWCAP_SM4;
92}
93
94#[cfg(target_vendor = "apple")]
106#[macro_export]
107#[doc(hidden)]
108macro_rules! check {
109 ("aes") => {
110 true
111 };
112 ("dit") => {
113 unsafe {
115 $crate::aarch64::sysctlbyname(b"hw.optional.arm.FEAT_DIT\0")
116 }
117 };
118 ("sha2") => {
119 true
120 };
121 ("sha3") => {
122 unsafe {
123 $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha512\0")
125 && $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha3\0")
126 }
127 };
128 ("sm4") => {
129 false
130 };
131}
132
133#[cfg(target_vendor = "apple")]
135pub unsafe fn sysctlbyname(name: &[u8]) -> bool {
136 assert_eq!(
137 name.last().cloned(),
138 Some(0),
139 "name is not NUL terminated: {:?}",
140 name
141 );
142
143 let mut value: u32 = 0;
144 let mut size = core::mem::size_of::<u32>();
145
146 let rc = libc::sysctlbyname(
147 name.as_ptr() as *const i8,
148 &mut value as *mut _ as *mut libc::c_void,
149 &mut size,
150 core::ptr::null_mut(),
151 0,
152 );
153
154 assert_eq!(size, 4, "unexpected sysctlbyname(3) result size");
155 assert_eq!(rc, 0, "sysctlbyname returned error code: {}", rc);
156 value != 0
157}
158
159#[cfg(not(any(target_vendor = "apple", target_os = "linux", target_os = "android",)))]
161#[macro_export]
162#[doc(hidden)]
163macro_rules! __detect_target_features {
164 ($($tf:tt),+) => {
165 false
166 };
167}