@@ -7,7 +7,7 @@ use crate::detect::{bit, cache, Feature};
7
7
/// to read them from /proc/cpuinfo.
8
8
pub ( crate ) fn detect_features ( ) -> cache:: Initializer {
9
9
#[ cfg( all( target_arch = "aarch64" , target_os = "android" ) ) ]
10
- {
10
+ let is_exynos9810 = {
11
11
// Samsung Exynos 9810 has a bug that big and little cores have different
12
12
// ISAs. And on older Android (pre-9), the kernel incorrectly reports
13
13
// that features available only on some cores are available on all cores.
@@ -21,18 +21,19 @@ pub(crate) fn detect_features() -> cache::Initializer {
21
21
} ;
22
22
// On Exynos, ro.arch is not available on Android 12+, but it is fine
23
23
// because Android 9+ includes the fix.
24
- if len > 0 && arch. starts_with ( b"exynos9810" ) {
25
- return cache:: Initializer :: default ( ) ;
26
- }
27
- }
24
+ len > 0 && arch. starts_with ( b"exynos9810" )
25
+ } ;
26
+ #[ cfg( not( all( target_arch = "aarch64" , target_os = "android" ) ) ) ]
27
+ let is_exynos9810 = false ;
28
+
28
29
if let Ok ( auxv) = auxvec:: auxv ( ) {
29
30
let hwcap: AtHwcap = auxv. into ( ) ;
30
- return hwcap. cache ( ) ;
31
+ return hwcap. cache ( is_exynos9810 ) ;
31
32
}
32
33
#[ cfg( feature = "std_detect_file_io" ) ]
33
34
if let Ok ( c) = super :: cpuinfo:: CpuInfo :: new ( ) {
34
35
let hwcap: AtHwcap = c. into ( ) ;
35
- return hwcap. cache ( ) ;
36
+ return hwcap. cache ( is_exynos9810 ) ;
36
37
}
37
38
cache:: Initializer :: default ( )
38
39
}
@@ -228,7 +229,7 @@ impl AtHwcap {
228
229
///
229
230
/// The feature dependencies here come directly from LLVM's feature definintions:
230
231
/// https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64.td
231
- fn cache ( self ) -> cache:: Initializer {
232
+ fn cache ( self , is_exynos9810 : bool ) -> cache:: Initializer {
232
233
let mut value = cache:: Initializer :: default ( ) ;
233
234
{
234
235
let mut enable_feature = |f, enable| {
@@ -237,6 +238,24 @@ impl AtHwcap {
237
238
}
238
239
} ;
239
240
241
+ // Samsung Exynos 9810 has a bug that big and little cores have different
242
+ // ISAs. And on older Android (pre-9), the kernel incorrectly reports
243
+ // that features available only on some cores are available on all cores.
244
+ // So, only check features that are known to be available on exynos-m3:
245
+ // $ rustc --print cfg --target aarch64-linux-android -C target-cpu=exynos-m3 | grep target_feature
246
+ if is_exynos9810 {
247
+ enable_feature ( Feature :: fp, self . fp ) ;
248
+ enable_feature ( Feature :: crc, self . crc32 ) ;
249
+ // ASIMD support requires float support - if half-floats are
250
+ // supported, it also requires half-float support:
251
+ let asimd = self . fp && self . asimd && ( !self . fphp | self . asimdhp ) ;
252
+ enable_feature ( Feature :: asimd, asimd) ;
253
+ // Cryptographic extensions require ASIMD
254
+ enable_feature ( Feature :: aes, self . aes && asimd) ;
255
+ enable_feature ( Feature :: sha2, self . sha1 && self . sha2 && asimd) ;
256
+ return value;
257
+ }
258
+
240
259
enable_feature ( Feature :: fp, self . fp ) ;
241
260
// Half-float support requires float support
242
261
enable_feature ( Feature :: fp16, self . fp && self . fphp ) ;
0 commit comments