|
1 | 1 | // Written for Graviola by Joe Birr-Pixton, 2024. |
2 | 2 | // SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT-0 |
3 | 3 |
|
4 | | -use std::arch::is_aarch64_feature_detected; |
5 | | - |
6 | 4 | pub(crate) fn enter_cpu_state() -> u32 { |
7 | 5 | dit::maybe_enable() |
8 | 6 | } |
@@ -157,28 +155,77 @@ pub(in crate::low) unsafe fn ct_compare_bytes(a: *const u8, b: *const u8, len: u |
157 | 155 | } |
158 | 156 | } |
159 | 157 |
|
| 158 | +/// This macro interdicts is_aarch64_feature_detected to allow testability. |
| 159 | +macro_rules! have_cpu_feature { |
| 160 | + ("neon") => { |
| 161 | + crate::low::aarch64::cpu::test_toggle( |
| 162 | + "neon", |
| 163 | + std::arch::is_aarch64_feature_detected!("neon"), |
| 164 | + ) |
| 165 | + }; |
| 166 | + ("aes") => { |
| 167 | + crate::low::aarch64::cpu::test_toggle("aes", std::arch::is_aarch64_feature_detected!("aes")) |
| 168 | + }; |
| 169 | + ("pmull") => { |
| 170 | + crate::low::aarch64::cpu::test_toggle( |
| 171 | + "pmull", |
| 172 | + std::arch::is_aarch64_feature_detected!("pmull"), |
| 173 | + ) |
| 174 | + }; |
| 175 | + ("sha2") => { |
| 176 | + crate::low::aarch64::cpu::test_toggle( |
| 177 | + "sha2", |
| 178 | + std::arch::is_aarch64_feature_detected!("sha2"), |
| 179 | + ) |
| 180 | + }; |
| 181 | + ("sha3") => { |
| 182 | + crate::low::aarch64::cpu::test_toggle( |
| 183 | + "sha3", |
| 184 | + std::arch::is_aarch64_feature_detected!("sha3"), |
| 185 | + ) |
| 186 | + }; |
| 187 | + ("dit") => { |
| 188 | + crate::low::aarch64::cpu::test_toggle("dit", std::arch::is_aarch64_feature_detected!("dit")) |
| 189 | + }; |
| 190 | +} |
| 191 | + |
| 192 | +/// Token type reflecting the check for the SHA3 CPU feature |
| 193 | +/// |
| 194 | +/// A value of this type is proof that the CPU dynamic feature check has happened. |
| 195 | +#[derive(Clone, Copy, Debug)] |
| 196 | +pub(crate) struct HaveSha3(()); |
| 197 | + |
| 198 | +impl HaveSha3 { |
| 199 | + pub(crate) fn check() -> Option<Self> { |
| 200 | + match have_cpu_feature!("sha3") { |
| 201 | + true => Some(Self(())), |
| 202 | + false => None, |
| 203 | + } |
| 204 | + } |
| 205 | +} |
| 206 | + |
160 | 207 | pub(crate) fn verify_cpu_features() { |
161 | 208 | assert!( |
162 | | - is_aarch64_feature_detected!("neon"), |
| 209 | + have_cpu_feature!("neon"), |
163 | 210 | "graviola requires neon CPU support" |
164 | 211 | ); |
165 | 212 | assert!( |
166 | | - is_aarch64_feature_detected!("aes"), |
| 213 | + have_cpu_feature!("aes"), |
167 | 214 | "graviola requires aes CPU support" |
168 | 215 | ); |
169 | 216 | assert!( |
170 | | - is_aarch64_feature_detected!("pmull"), |
| 217 | + have_cpu_feature!("pmull"), |
171 | 218 | "graviola requires pmull CPU support" |
172 | 219 | ); |
173 | 220 | assert!( |
174 | | - is_aarch64_feature_detected!("sha2"), |
| 221 | + have_cpu_feature!("sha2"), |
175 | 222 | "graviola requires sha2 CPU support" |
176 | 223 | ); |
177 | 224 | } |
178 | 225 |
|
179 | 226 | mod dit { |
180 | 227 | pub(super) fn maybe_enable() -> u32 { |
181 | | - if super::is_aarch64_feature_detected!("dit") { |
| 228 | + if have_cpu_feature!("dit") { |
182 | 229 | // SAFETY: in this branch, we verified `dit` cpu feature is supported |
183 | 230 | match unsafe { read() } { |
184 | 231 | 0 => { |
@@ -229,6 +276,21 @@ mod dit { |
229 | 276 | } |
230 | 277 | } |
231 | 278 |
|
| 279 | +#[cfg(not(debug_assertions))] |
| 280 | +pub(crate) fn test_toggle(_id: &str, detected: bool) -> bool { |
| 281 | + detected |
| 282 | +} |
| 283 | + |
| 284 | +#[cfg(debug_assertions)] |
| 285 | +pub(crate) fn test_toggle(id: &str, detected: bool) -> bool { |
| 286 | + if std::env::var(format!("GRAVIOLA_CPU_DISABLE_{id}")).is_ok() { |
| 287 | + println!("DEBUG: denying cpuid {id:?}"); |
| 288 | + false |
| 289 | + } else { |
| 290 | + detected |
| 291 | + } |
| 292 | +} |
| 293 | + |
232 | 294 | /// Read-only prefetch hint. |
233 | 295 | pub(in crate::low) fn prefetch_ro<T>(ptr: *const T) { |
234 | 296 | // SAFETY: inline assembly |
|
0 commit comments