]> git.proxmox.com Git - rustc.git/blame - library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / library / stdarch / crates / std_detect / src / detect / os / linux / aarch64.rs
CommitLineData
83c7162d
XL
1//! Run-time feature detection for Aarch64 on Linux.
2
cdc7bbd5 3use super::auxvec;
74b04a01 4use crate::detect::{bit, cache, Feature};
83c7162d
XL
5
6/// Try to read the features from the auxiliary vector, and if that fails, try
7/// to read them from /proc/cpuinfo.
74b04a01 8pub(crate) fn detect_features() -> cache::Initializer {
83c7162d
XL
9 if let Ok(auxv) = auxvec::auxv() {
10 let hwcap: AtHwcap = auxv.into();
11 return hwcap.cache();
12 }
cdc7bbd5
XL
13 #[cfg(feature = "std_detect_file_io")]
14 if let Ok(c) = super::cpuinfo::CpuInfo::new() {
83c7162d
XL
15 let hwcap: AtHwcap = c.into();
16 return hwcap.cache();
17 }
18 cache::Initializer::default()
19}
20
21/// These values are part of the platform-specific [asm/hwcap.h][hwcap] .
22///
17df50a5
XL
23/// The names match those used for cpuinfo.
24///
83c7162d
XL
25/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
26struct AtHwcap {
74b04a01 27 fp: bool, // 0
83c7162d 28 asimd: bool, // 1
17df50a5 29 // evtstrm: bool, // 2 No LLVM support
74b04a01
XL
30 aes: bool, // 3
31 pmull: bool, // 4
32 sha1: bool, // 5
33 sha2: bool, // 6
34 crc32: bool, // 7
83c7162d 35 atomics: bool, // 8
74b04a01 36 fphp: bool, // 9
83c7162d 37 asimdhp: bool, // 10
17df50a5 38 // cpuid: bool, // 11 No LLVM support
83c7162d 39 asimdrdm: bool, // 12
17df50a5
XL
40 jscvt: bool, // 13
41 fcma: bool, // 14
42 lrcpc: bool, // 15
43 dcpop: bool, // 16
44 sha3: bool, // 17
45 sm3: bool, // 18
46 sm4: bool, // 19
47 asimddp: bool, // 20
48 sha512: bool, // 21
49 sve: bool, // 22
50 fhm: bool, // 23
51 dit: bool, // 24
52 uscat: bool, // 25
53 ilrcpc: bool, // 26
54 flagm: bool, // 27
55 ssbs: bool, // 28
56 sb: bool, // 29
57 paca: bool, // 30
58 pacg: bool, // 31
59 dcpodp: bool, // 32
60 sve2: bool, // 33
61 sveaes: bool, // 34
62 // svepmull: bool, // 35 No LLVM support
63 svebitperm: bool, // 36
64 svesha3: bool, // 37
65 svesm4: bool, // 38
66 // flagm2: bool, // 39 No LLVM support
67 frint: bool, // 40
68 // svei8mm: bool, // 41 See i8mm feature
69 svef32mm: bool, // 42
70 svef64mm: bool, // 43
71 // svebf16: bool, // 44 See bf16 feature
72 i8mm: bool, // 45
73 bf16: bool, // 46
74 // dgh: bool, // 47 No LLVM support
75 rng: bool, // 48
76 bti: bool, // 49
77 mte: bool, // 50
83c7162d
XL
78}
79
80impl From<auxvec::AuxVec> for AtHwcap {
81 /// Reads AtHwcap from the auxiliary vector.
82 fn from(auxv: auxvec::AuxVec) -> Self {
83 AtHwcap {
84 fp: bit::test(auxv.hwcap, 0),
85 asimd: bit::test(auxv.hwcap, 1),
86 // evtstrm: bit::test(auxv.hwcap, 2),
87 aes: bit::test(auxv.hwcap, 3),
88 pmull: bit::test(auxv.hwcap, 4),
89 sha1: bit::test(auxv.hwcap, 5),
90 sha2: bit::test(auxv.hwcap, 6),
91 crc32: bit::test(auxv.hwcap, 7),
92 atomics: bit::test(auxv.hwcap, 8),
93 fphp: bit::test(auxv.hwcap, 9),
94 asimdhp: bit::test(auxv.hwcap, 10),
95 // cpuid: bit::test(auxv.hwcap, 11),
96 asimdrdm: bit::test(auxv.hwcap, 12),
17df50a5
XL
97 jscvt: bit::test(auxv.hwcap, 13),
98 fcma: bit::test(auxv.hwcap, 14),
83c7162d 99 lrcpc: bit::test(auxv.hwcap, 15),
17df50a5
XL
100 dcpop: bit::test(auxv.hwcap, 16),
101 sha3: bit::test(auxv.hwcap, 17),
102 sm3: bit::test(auxv.hwcap, 18),
103 sm4: bit::test(auxv.hwcap, 19),
83c7162d 104 asimddp: bit::test(auxv.hwcap, 20),
17df50a5 105 sha512: bit::test(auxv.hwcap, 21),
83c7162d 106 sve: bit::test(auxv.hwcap, 22),
17df50a5
XL
107 fhm: bit::test(auxv.hwcap, 23),
108 dit: bit::test(auxv.hwcap, 24),
109 uscat: bit::test(auxv.hwcap, 25),
110 ilrcpc: bit::test(auxv.hwcap, 26),
111 flagm: bit::test(auxv.hwcap, 27),
112 ssbs: bit::test(auxv.hwcap, 28),
113 sb: bit::test(auxv.hwcap, 29),
114 paca: bit::test(auxv.hwcap, 30),
115 pacg: bit::test(auxv.hwcap, 31),
116 dcpodp: bit::test(auxv.hwcap, 32),
117 sve2: bit::test(auxv.hwcap, 33),
118 sveaes: bit::test(auxv.hwcap, 34),
119 // svepmull: bit::test(auxv.hwcap, 35),
120 svebitperm: bit::test(auxv.hwcap, 36),
121 svesha3: bit::test(auxv.hwcap, 37),
122 svesm4: bit::test(auxv.hwcap, 38),
123 // flagm2: bit::test(auxv.hwcap, 39),
124 frint: bit::test(auxv.hwcap, 40),
125 // svei8mm: bit::test(auxv.hwcap, 41),
126 svef32mm: bit::test(auxv.hwcap, 42),
127 svef64mm: bit::test(auxv.hwcap, 43),
128 // svebf16: bit::test(auxv.hwcap, 44),
129 i8mm: bit::test(auxv.hwcap, 45),
130 bf16: bit::test(auxv.hwcap, 46),
131 // dgh: bit::test(auxv.hwcap, 47),
132 rng: bit::test(auxv.hwcap, 48),
133 bti: bit::test(auxv.hwcap, 49),
134 mte: bit::test(auxv.hwcap, 50),
83c7162d
XL
135 }
136 }
137}
138
cdc7bbd5
XL
139#[cfg(feature = "std_detect_file_io")]
140impl From<super::cpuinfo::CpuInfo> for AtHwcap {
83c7162d 141 /// Reads AtHwcap from /proc/cpuinfo .
cdc7bbd5 142 fn from(c: super::cpuinfo::CpuInfo) -> Self {
83c7162d
XL
143 let f = &c.field("Features");
144 AtHwcap {
145 // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will
146 // map some of the 64-bit names to some 32-bit feature names. This does not
147 // cover that yet.
148 fp: f.has("fp"),
149 asimd: f.has("asimd"),
150 // evtstrm: f.has("evtstrm"),
151 aes: f.has("aes"),
152 pmull: f.has("pmull"),
153 sha1: f.has("sha1"),
154 sha2: f.has("sha2"),
155 crc32: f.has("crc32"),
156 atomics: f.has("atomics"),
157 fphp: f.has("fphp"),
158 asimdhp: f.has("asimdhp"),
159 // cpuid: f.has("cpuid"),
160 asimdrdm: f.has("asimdrdm"),
17df50a5
XL
161 jscvt: f.has("jscvt"),
162 fcma: f.has("fcma"),
83c7162d 163 lrcpc: f.has("lrcpc"),
17df50a5
XL
164 dcpop: f.has("dcpop"),
165 sha3: f.has("sha3"),
166 sm3: f.has("sm3"),
167 sm4: f.has("sm4"),
83c7162d 168 asimddp: f.has("asimddp"),
17df50a5 169 sha512: f.has("sha512"),
83c7162d 170 sve: f.has("sve"),
17df50a5
XL
171 fhm: f.has("asimdfhm"),
172 dit: f.has("dit"),
173 uscat: f.has("uscat"),
174 ilrcpc: f.has("ilrcpc"),
175 flagm: f.has("flagm"),
176 ssbs: f.has("ssbs"),
177 sb: f.has("sb"),
178 paca: f.has("paca"),
179 pacg: f.has("pacg"),
180 dcpodp: f.has("dcpodp"),
181 sve2: f.has("sve2"),
182 sveaes: f.has("sveaes"),
183 // svepmull: f.has("svepmull"),
184 svebitperm: f.has("svebitperm"),
185 svesha3: f.has("svesha3"),
186 svesm4: f.has("svesm4"),
187 // flagm2: f.has("flagm2"),
188 frint: f.has("frint"),
189 // svei8mm: f.has("svei8mm"),
190 svef32mm: f.has("svef32mm"),
191 svef64mm: f.has("svef64mm"),
192 // svebf16: f.has("svebf16"),
193 i8mm: f.has("i8mm"),
194 bf16: f.has("bf16"),
195 // dgh: f.has("dgh"),
196 rng: f.has("rng"),
197 bti: f.has("bti"),
198 mte: f.has("mte"),
83c7162d
XL
199 }
200 }
201}
202
203impl AtHwcap {
204 /// Initializes the cache from the feature -bits.
205 ///
17df50a5
XL
206 /// The feature dependencies here come directly from LLVM's feature definintions:
207 /// https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64.td
8faf50e0 208 fn cache(self) -> cache::Initializer {
83c7162d
XL
209 let mut value = cache::Initializer::default();
210 {
211 let mut enable_feature = |f, enable| {
212 if enable {
213 value.set(f as u32);
214 }
215 };
216
217 enable_feature(Feature::fp, self.fp);
218 // Half-float support requires float support
219 enable_feature(Feature::fp16, self.fp && self.fphp);
17df50a5
XL
220 // FHM (fp16fml in LLVM) requires half float support
221 enable_feature(Feature::fhm, self.fphp && self.fhm);
83c7162d
XL
222 enable_feature(Feature::pmull, self.pmull);
223 enable_feature(Feature::crc, self.crc32);
224 enable_feature(Feature::lse, self.atomics);
17df50a5 225 enable_feature(Feature::lse2, self.uscat);
83c7162d 226 enable_feature(Feature::rcpc, self.lrcpc);
17df50a5
XL
227 // RCPC2 (rcpc-immo in LLVM) requires RCPC support
228 enable_feature(Feature::rcpc2, self.ilrcpc && self.lrcpc);
229 enable_feature(Feature::dit, self.dit);
230 enable_feature(Feature::flagm, self.flagm);
231 enable_feature(Feature::ssbs, self.ssbs);
232 enable_feature(Feature::sb, self.sb);
233 // FEAT_PAuth provides both paca & pacg
234 enable_feature(Feature::pauth, self.paca && self.pacg);
235 enable_feature(Feature::dpb, self.dcpop);
236 enable_feature(Feature::dpb2, self.dcpodp);
237 enable_feature(Feature::rand, self.rng);
238 enable_feature(Feature::bti, self.bti);
239 enable_feature(Feature::mte, self.mte);
240 // jsconv requires float support
241 enable_feature(Feature::jsconv, self.jscvt && self.fp);
242 enable_feature(Feature::rdm, self.asimdrdm);
243 enable_feature(Feature::dotprod, self.asimddp);
244 enable_feature(Feature::frintts, self.frint);
245
246 // FEAT_I8MM & FEAT_BF16 also include optional SVE components which linux exposes
247 // separately. We ignore that distinction here.
248 enable_feature(Feature::i8mm, self.i8mm);
249 enable_feature(Feature::bf16, self.bf16);
83c7162d 250
17df50a5 251 // ASIMD support requires float support - if half-floats are
83c7162d
XL
252 // supported, it also requires half-float support:
253 let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp);
254 enable_feature(Feature::asimd, asimd);
17df50a5
XL
255 // ASIMD extensions require ASIMD support:
256 enable_feature(Feature::fcma, self.fcma && asimd);
83c7162d
XL
257 enable_feature(Feature::sve, self.sve && asimd);
258
17df50a5
XL
259 // SVE extensions require SVE & ASIMD
260 enable_feature(Feature::f32mm, self.svef32mm && self.sve && asimd);
261 enable_feature(Feature::f64mm, self.svef64mm && self.sve && asimd);
262
263 // Cryptographic extensions require ASIMD
264 enable_feature(Feature::aes, self.aes && asimd);
265 enable_feature(Feature::sha2, self.sha1 && self.sha2 && asimd);
266 // SHA512/SHA3 require SHA1 & SHA256
267 enable_feature(
268 Feature::sha3,
269 self.sha512 && self.sha3 && self.sha1 && self.sha2 && asimd,
270 );
271 enable_feature(Feature::sm4, self.sm3 && self.sm4 && asimd);
272
273 // SVE2 requires SVE
274 let sve2 = self.sve2 && self.sve && asimd;
275 enable_feature(Feature::sve2, sve2);
276 // SVE2 extensions require SVE2 and crypto features
277 enable_feature(Feature::sve2_aes, self.sveaes && sve2 && self.aes);
278 enable_feature(
279 Feature::sve2_sm4,
280 self.svesm4 && sve2 && self.sm3 && self.sm4,
281 );
74b04a01 282 enable_feature(
17df50a5
XL
283 Feature::sve2_sha3,
284 self.svesha3 && sve2 && self.sha512 && self.sha3 && self.sha1 && self.sha2,
74b04a01 285 );
17df50a5 286 enable_feature(Feature::sve2_bitperm, self.svebitperm && self.sve2);
83c7162d
XL
287 }
288 value
289 }
290}