@@ -23,77 +23,86 @@ use core::arch::asm;
2323///
2424/// This will cause SIGILL if the current OS is not trapping the mrs instruction.
2525pub ( crate ) fn detect_features ( ) -> cache:: Initializer {
26- let mut value = cache:: Initializer :: default ( ) ;
26+ // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
27+ let aa64isar0: u64 ;
28+ unsafe {
29+ asm ! (
30+ "mrs {}, ID_AA64ISAR0_EL1" ,
31+ out( reg) aa64isar0,
32+ options( pure, nomem, preserves_flags, nostack)
33+ ) ;
34+ }
2735
28- {
29- let mut enable_feature = |f, enable| {
30- if enable {
31- value. set ( f as u32 ) ;
32- }
33- } ;
36+ // ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
37+ let aa64isar1: u64 ;
38+ unsafe {
39+ asm ! (
40+ "mrs {}, ID_AA64ISAR1_EL1" ,
41+ out( reg) aa64isar1,
42+ options( pure, nomem, preserves_flags, nostack)
43+ ) ;
44+ }
3445
35- // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
36- let aa64isar0: u64 ;
37- unsafe {
38- asm ! (
39- "mrs {}, ID_AA64ISAR0_EL1" ,
40- out( reg) aa64isar0,
41- options( pure, nomem, preserves_flags, nostack)
42- ) ;
43- }
46+ // ID_AA64PFR0_EL1 - Processor Feature Register 0
47+ let aa64pfr0: u64 ;
48+ unsafe {
49+ asm ! (
50+ "mrs {}, ID_AA64PFR0_EL1" ,
51+ out( reg) aa64pfr0,
52+ options( pure, nomem, preserves_flags, nostack)
53+ ) ;
54+ }
55+
56+ parse_system_registers ( aa64isar0, aa64isar1, aa64pfr0)
57+ }
4458
45- enable_feature ( Feature :: pmull, bits_shift ( aa64isar0, 7 , 4 ) >= 2 ) ;
46- enable_feature ( Feature :: tme, bits_shift ( aa64isar0, 27 , 24 ) == 1 ) ;
47- enable_feature ( Feature :: lse, bits_shift ( aa64isar0, 23 , 20 ) >= 1 ) ;
48- enable_feature ( Feature :: crc, bits_shift ( aa64isar0, 19 , 16 ) >= 1 ) ;
59+ pub ( crate ) fn parse_system_registers (
60+ aa64isar0 : u64 ,
61+ aa64isar1 : u64 ,
62+ aa64pfr0 : u64 ,
63+ ) -> cache:: Initializer {
64+ let mut value = cache:: Initializer :: default ( ) ;
4965
50- // ID_AA64PFR0_EL1 - Processor Feature Register 0
51- let aa64pfr0: u64 ;
52- unsafe {
53- asm ! (
54- "mrs {}, ID_AA64PFR0_EL1" ,
55- out( reg) aa64pfr0,
56- options( pure, nomem, preserves_flags, nostack)
57- ) ;
66+ let mut enable_feature = |f, enable| {
67+ if enable {
68+ value. set ( f as u32 ) ;
5869 }
70+ } ;
5971
60- let fp = bits_shift ( aa64pfr0, 19 , 16 ) < 0xF ;
61- let fphp = bits_shift ( aa64pfr0, 19 , 16 ) >= 1 ;
62- let asimd = bits_shift ( aa64pfr0, 23 , 20 ) < 0xF ;
63- let asimdhp = bits_shift ( aa64pfr0, 23 , 20 ) >= 1 ;
64- enable_feature ( Feature :: fp, fp) ;
65- enable_feature ( Feature :: fp16, fphp) ;
66- // SIMD support requires float support - if half-floats are
67- // supported, it also requires half-float support:
68- enable_feature ( Feature :: asimd, fp && asimd && ( !fphp | asimdhp) ) ;
69- // SIMD extensions require SIMD support:
70- enable_feature ( Feature :: aes, asimd && bits_shift ( aa64isar0, 7 , 4 ) >= 1 ) ;
71- let sha1 = bits_shift ( aa64isar0, 11 , 8 ) >= 1 ;
72- let sha2 = bits_shift ( aa64isar0, 15 , 12 ) >= 1 ;
73- enable_feature ( Feature :: sha2, asimd && sha1 && sha2) ;
74- enable_feature ( Feature :: rdm, asimd && bits_shift ( aa64isar0, 31 , 28 ) >= 1 ) ;
75- enable_feature (
76- Feature :: dotprod,
77- asimd && bits_shift ( aa64isar0, 47 , 44 ) >= 1 ,
78- ) ;
79- enable_feature ( Feature :: sve, asimd && bits_shift ( aa64pfr0, 35 , 32 ) >= 1 ) ;
72+ // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
73+ enable_feature ( Feature :: pmull, bits_shift ( aa64isar0, 7 , 4 ) >= 2 ) ;
74+ enable_feature ( Feature :: tme, bits_shift ( aa64isar0, 27 , 24 ) == 1 ) ;
75+ enable_feature ( Feature :: lse, bits_shift ( aa64isar0, 23 , 20 ) >= 1 ) ;
76+ enable_feature ( Feature :: crc, bits_shift ( aa64isar0, 19 , 16 ) >= 1 ) ;
8077
81- // ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
82- let aa64isar1: u64 ;
83- unsafe {
84- asm ! (
85- "mrs {}, ID_AA64ISAR1_EL1" ,
86- out( reg) aa64isar1,
87- options( pure, nomem, preserves_flags, nostack)
88- ) ;
89- }
78+ // ID_AA64PFR0_EL1 - Processor Feature Register 0
79+ let fp = bits_shift ( aa64pfr0, 19 , 16 ) < 0xF ;
80+ let fphp = bits_shift ( aa64pfr0, 19 , 16 ) >= 1 ;
81+ let asimd = bits_shift ( aa64pfr0, 23 , 20 ) < 0xF ;
82+ let asimdhp = bits_shift ( aa64pfr0, 23 , 20 ) >= 1 ;
83+ enable_feature ( Feature :: fp, fp) ;
84+ enable_feature ( Feature :: fp16, fphp) ;
85+ // SIMD support requires float support - if half-floats are
86+ // supported, it also requires half-float support:
87+ enable_feature ( Feature :: asimd, fp && asimd && ( !fphp | asimdhp) ) ;
88+ // SIMD extensions require SIMD support:
89+ enable_feature ( Feature :: aes, asimd && bits_shift ( aa64isar0, 7 , 4 ) >= 1 ) ;
90+ let sha1 = bits_shift ( aa64isar0, 11 , 8 ) >= 1 ;
91+ let sha2 = bits_shift ( aa64isar0, 15 , 12 ) >= 1 ;
92+ enable_feature ( Feature :: sha2, asimd && sha1 && sha2) ;
93+ enable_feature ( Feature :: rdm, asimd && bits_shift ( aa64isar0, 31 , 28 ) >= 1 ) ;
94+ enable_feature (
95+ Feature :: dotprod,
96+ asimd && bits_shift ( aa64isar0, 47 , 44 ) >= 1 ,
97+ ) ;
98+ enable_feature ( Feature :: sve, asimd && bits_shift ( aa64pfr0, 35 , 32 ) >= 1 ) ;
9099
91- // Check for either APA or API field
92- enable_feature ( Feature :: paca , bits_shift ( aa64isar1 , 11 , 4 ) >= 1 ) ;
93- enable_feature ( Feature :: rcpc , bits_shift ( aa64isar1, 23 , 20 ) >= 1 ) ;
94- // Check for either GPA or GPI field
95- enable_feature ( Feature :: pacg , bits_shift ( aa64isar1 , 31 , 24 ) >= 1 ) ;
96- }
100+ // ID_AA64PFR0_EL1 - Processor Feature Register 0
101+ // Check for either APA or API field
102+ enable_feature ( Feature :: paca , bits_shift ( aa64isar1, 11 , 4 ) >= 1 ) ;
103+ enable_feature ( Feature :: rcpc , bits_shift ( aa64isar1 , 23 , 20 ) >= 1 ) ;
104+ // Check for either GPA or GPI field
105+ enable_feature ( Feature :: pacg , bits_shift ( aa64isar1 , 31 , 24 ) >= 1 ) ;
97106
98107 value
99108}
0 commit comments