1 /*
2 * QEMU Arm CPU -- feature test functions
3 *
4 * Copyright (c) 2023 Linaro Ltd
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef TARGET_ARM_FEATURES_H
21 #define TARGET_ARM_FEATURES_H
22
23 #include "hw/registerfields.h"
24 #include "qemu/host-utils.h"
25 #include "cpu.h"
26 #include "cpu-sysregs.h"
27
28 /*
29 * Naming convention for isar_feature functions:
30 * Functions which test 32-bit ID registers should have _aa32_ in
31 * their name. Functions which test 64-bit ID registers should have
32 * _aa64_ in their name. These must only be used in code where we
33 * know for certain that the CPU has AArch32 or AArch64 respectively
34 * or where the correct answer for a CPU which doesn't implement that
35 * CPU state is "false" (eg when generating A32 or A64 code, if adding
36 * system registers that are specific to that CPU state, for "should
37 * we let this system register bit be set" tests where the 32-bit
38 * flavour of the register doesn't have the bit, and so on).
39 * Functions which simply ask "does this feature exist at all" have
40 * _any_ in their name, and always return the logical OR of the _aa64_
41 * and the _aa32_ function.
42 */
43
44 /*
45 * 32-bit feature tests via id registers.
46 */
isar_feature_aa32_thumb_div(const ARMISARegisters * id)47 static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id)
48 {
49 return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) != 0;
50 }
51
isar_feature_aa32_arm_div(const ARMISARegisters * id)52 static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
53 {
54 return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) > 1;
55 }
56
isar_feature_aa32_lob(const ARMISARegisters * id)57 static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
58 {
59 /* (M-profile) low-overhead loops and branch future */
60 return FIELD_EX32_IDREG(id, ID_ISAR0, CMPBRANCH) >= 3;
61 }
62
isar_feature_aa32_jazelle(const ARMISARegisters * id)63 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
64 {
65 return FIELD_EX32_IDREG(id, ID_ISAR1, JAZELLE) != 0;
66 }
67
isar_feature_aa32_aes(const ARMISARegisters * id)68 static inline bool isar_feature_aa32_aes(const ARMISARegisters *id)
69 {
70 return FIELD_EX32_IDREG(id, ID_ISAR5, AES) != 0;
71 }
72
isar_feature_aa32_pmull(const ARMISARegisters * id)73 static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id)
74 {
75 return FIELD_EX32_IDREG(id, ID_ISAR5, AES) > 1;
76 }
77
isar_feature_aa32_sha1(const ARMISARegisters * id)78 static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id)
79 {
80 return FIELD_EX32_IDREG(id, ID_ISAR5, SHA1) != 0;
81 }
82
isar_feature_aa32_sha2(const ARMISARegisters * id)83 static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id)
84 {
85 return FIELD_EX32_IDREG(id, ID_ISAR5, SHA2) != 0;
86 }
87
isar_feature_aa32_crc32(const ARMISARegisters * id)88 static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id)
89 {
90 return FIELD_EX32_IDREG(id, ID_ISAR5, CRC32) != 0;
91 }
92
isar_feature_aa32_rdm(const ARMISARegisters * id)93 static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id)
94 {
95 return FIELD_EX32_IDREG(id, ID_ISAR5, RDM) != 0;
96 }
97
isar_feature_aa32_vcma(const ARMISARegisters * id)98 static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
99 {
100 return FIELD_EX32_IDREG(id, ID_ISAR5, VCMA) != 0;
101 }
102
isar_feature_aa32_jscvt(const ARMISARegisters * id)103 static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
104 {
105 return FIELD_EX32_IDREG(id, ID_ISAR6, JSCVT) != 0;
106 }
107
isar_feature_aa32_dp(const ARMISARegisters * id)108 static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
109 {
110 return FIELD_EX32_IDREG(id, ID_ISAR6, DP) != 0;
111 }
112
isar_feature_aa32_fhm(const ARMISARegisters * id)113 static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
114 {
115 return FIELD_EX32_IDREG(id, ID_ISAR6, FHM) != 0;
116 }
117
isar_feature_aa32_sb(const ARMISARegisters * id)118 static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
119 {
120 return FIELD_EX32_IDREG(id, ID_ISAR6, SB) != 0;
121 }
122
isar_feature_aa32_predinv(const ARMISARegisters * id)123 static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
124 {
125 return FIELD_EX32_IDREG(id, ID_ISAR6, SPECRES) != 0;
126 }
127
isar_feature_aa32_bf16(const ARMISARegisters * id)128 static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id)
129 {
130 return FIELD_EX32_IDREG(id, ID_ISAR6, BF16) != 0;
131 }
132
isar_feature_aa32_i8mm(const ARMISARegisters * id)133 static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
134 {
135 return FIELD_EX32_IDREG(id, ID_ISAR6, I8MM) != 0;
136 }
137
isar_feature_aa32_ras(const ARMISARegisters * id)138 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
139 {
140 return FIELD_EX32_IDREG(id, ID_PFR0, RAS) != 0;
141 }
142
isar_feature_aa32_mprofile(const ARMISARegisters * id)143 static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
144 {
145 return FIELD_EX32_IDREG(id, ID_PFR1, MPROGMOD) != 0;
146 }
147
isar_feature_aa32_m_sec_state(const ARMISARegisters * id)148 static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
149 {
150 /*
151 * Return true if M-profile state handling insns
152 * (VSCCLRM, CLRM, FPCTX access insns) are implemented
153 */
154 return FIELD_EX32_IDREG(id, ID_PFR1, SECURITY) >= 3;
155 }
156
isar_feature_aa32_fp16_arith(const ARMISARegisters * id)157 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
158 {
159 /* Sadly this is encoded differently for A-profile and M-profile */
160 if (isar_feature_aa32_mprofile(id)) {
161 return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0;
162 } else {
163 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3;
164 }
165 }
166
isar_feature_aa32_mve(const ARMISARegisters * id)167 static inline bool isar_feature_aa32_mve(const ARMISARegisters *id)
168 {
169 /*
170 * Return true if MVE is supported (either integer or floating point).
171 * We must check for M-profile as the MVFR1 field means something
172 * else for A-profile.
173 */
174 return isar_feature_aa32_mprofile(id) &&
175 FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0;
176 }
177
isar_feature_aa32_mve_fp(const ARMISARegisters * id)178 static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id)
179 {
180 /*
181 * Return true if MVE is supported (either integer or floating point).
182 * We must check for M-profile as the MVFR1 field means something
183 * else for A-profile.
184 */
185 return isar_feature_aa32_mprofile(id) &&
186 FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2;
187 }
188
isar_feature_aa32_vfp_simd(const ARMISARegisters * id)189 static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
190 {
191 /*
192 * Return true if either VFP or SIMD is implemented.
193 * In this case, a minimum of VFP w/ D0-D15.
194 */
195 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
196 }
197
isar_feature_aa32_simd_r32(const ARMISARegisters * id)198 static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
199 {
200 /* Return true if D16-D31 are implemented */
201 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2;
202 }
203
isar_feature_aa32_fpshvec(const ARMISARegisters * id)204 static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
205 {
206 return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
207 }
208
isar_feature_aa32_fpsp_v2(const ARMISARegisters * id)209 static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
210 {
211 /* Return true if CPU supports single precision floating point, VFPv2 */
212 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
213 }
214
isar_feature_aa32_fpsp_v3(const ARMISARegisters * id)215 static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
216 {
217 /* Return true if CPU supports single precision floating point, VFPv3 */
218 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
219 }
220
isar_feature_aa32_fpdp_v2(const ARMISARegisters * id)221 static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
222 {
223 /* Return true if CPU supports double precision floating point, VFPv2 */
224 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
225 }
226
isar_feature_aa32_fpdp_v3(const ARMISARegisters * id)227 static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
228 {
229 /* Return true if CPU supports double precision floating point, VFPv3 */
230 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
231 }
232
isar_feature_aa32_vfp(const ARMISARegisters * id)233 static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
234 {
235 return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id);
236 }
237
238 /*
239 * We always set the FP and SIMD FP16 fields to indicate identical
240 * levels of support (assuming SIMD is implemented at all), so
241 * we only need one set of accessors.
242 */
isar_feature_aa32_fp16_spconv(const ARMISARegisters * id)243 static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
244 {
245 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0;
246 }
247
isar_feature_aa32_fp16_dpconv(const ARMISARegisters * id)248 static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
249 {
250 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
251 }
252
253 /*
254 * Note that this ID register field covers both VFP and Neon FMAC,
255 * so should usually be tested in combination with some other
256 * check that confirms the presence of whichever of VFP or Neon is
257 * relevant, to avoid accidentally enabling a Neon feature on
258 * a VFP-no-Neon core or vice-versa.
259 */
isar_feature_aa32_simdfmac(const ARMISARegisters * id)260 static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
261 {
262 return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
263 }
264
isar_feature_aa32_vsel(const ARMISARegisters * id)265 static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
266 {
267 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
268 }
269
isar_feature_aa32_vcvt_dr(const ARMISARegisters * id)270 static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
271 {
272 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2;
273 }
274
isar_feature_aa32_vrint(const ARMISARegisters * id)275 static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
276 {
277 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3;
278 }
279
isar_feature_aa32_vminmaxnm(const ARMISARegisters * id)280 static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
281 {
282 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4;
283 }
284
isar_feature_aa32_pxn(const ARMISARegisters * id)285 static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id)
286 {
287 return FIELD_EX32_IDREG(id, ID_MMFR0, VMSA) >= 4;
288 }
289
isar_feature_aa32_pan(const ARMISARegisters * id)290 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
291 {
292 return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) != 0;
293 }
294
isar_feature_aa32_ats1e1(const ARMISARegisters * id)295 static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
296 {
297 return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) >= 2;
298 }
299
isar_feature_aa32_pmuv3p1(const ARMISARegisters * id)300 static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id)
301 {
302 /* 0xf means "non-standard IMPDEF PMU" */
303 return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 4 &&
304 FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf;
305 }
306
isar_feature_aa32_pmuv3p4(const ARMISARegisters * id)307 static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id)
308 {
309 /* 0xf means "non-standard IMPDEF PMU" */
310 return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 5 &&
311 FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf;
312 }
313
isar_feature_aa32_pmuv3p5(const ARMISARegisters * id)314 static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id)
315 {
316 /* 0xf means "non-standard IMPDEF PMU" */
317 return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 6 &&
318 FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf;
319 }
320
isar_feature_aa32_hpd(const ARMISARegisters * id)321 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
322 {
323 return FIELD_EX32_IDREG(id, ID_MMFR4, HPDS) != 0;
324 }
325
isar_feature_aa32_ac2(const ARMISARegisters * id)326 static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
327 {
328 return FIELD_EX32_IDREG(id, ID_MMFR4, AC2) != 0;
329 }
330
isar_feature_aa32_ccidx(const ARMISARegisters * id)331 static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
332 {
333 return FIELD_EX32_IDREG(id, ID_MMFR4, CCIDX) != 0;
334 }
335
isar_feature_aa32_tts2uxn(const ARMISARegisters * id)336 static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
337 {
338 return FIELD_EX32_IDREG(id, ID_MMFR4, XNX) != 0;
339 }
340
isar_feature_aa32_half_evt(const ARMISARegisters * id)341 static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id)
342 {
343 return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 1;
344 }
345
isar_feature_aa32_evt(const ARMISARegisters * id)346 static inline bool isar_feature_aa32_evt(const ARMISARegisters *id)
347 {
348 return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 2;
349 }
350
isar_feature_aa32_dit(const ARMISARegisters * id)351 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
352 {
353 return FIELD_EX32_IDREG(id, ID_PFR0, DIT) != 0;
354 }
355
isar_feature_aa32_ssbs(const ARMISARegisters * id)356 static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
357 {
358 return FIELD_EX32_IDREG(id, ID_PFR2, SSBS) != 0;
359 }
360
isar_feature_aa32_debugv7p1(const ARMISARegisters * id)361 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
362 {
363 return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 5;
364 }
365
isar_feature_aa32_debugv8p2(const ARMISARegisters * id)366 static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
367 {
368 return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 8;
369 }
370
isar_feature_aa32_doublelock(const ARMISARegisters * id)371 static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id)
372 {
373 return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0;
374 }
375
376 /*
377 * 64-bit feature tests via id registers.
378 */
isar_feature_aa64_aes(const ARMISARegisters * id)379 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
380 {
381 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) != 0;
382 }
383
isar_feature_aa64_pmull(const ARMISARegisters * id)384 static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id)
385 {
386 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) > 1;
387 }
388
isar_feature_aa64_sha1(const ARMISARegisters * id)389 static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id)
390 {
391 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA1) != 0;
392 }
393
isar_feature_aa64_sha256(const ARMISARegisters * id)394 static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id)
395 {
396 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) != 0;
397 }
398
isar_feature_aa64_sha512(const ARMISARegisters * id)399 static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id)
400 {
401 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) > 1;
402 }
403
isar_feature_aa64_crc32(const ARMISARegisters * id)404 static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id)
405 {
406 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, CRC32) != 0;
407 }
408
isar_feature_aa64_atomics(const ARMISARegisters * id)409 static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id)
410 {
411 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, ATOMIC) != 0;
412 }
413
isar_feature_aa64_rdm(const ARMISARegisters * id)414 static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
415 {
416 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0;
417 }
418
isar_feature_aa64_sha3(const ARMISARegisters * id)419 static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id)
420 {
421 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA3) != 0;
422 }
423
isar_feature_aa64_sm3(const ARMISARegisters * id)424 static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id)
425 {
426 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM3) != 0;
427 }
428
isar_feature_aa64_sm4(const ARMISARegisters * id)429 static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id)
430 {
431 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM4) != 0;
432 }
433
isar_feature_aa64_dp(const ARMISARegisters * id)434 static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
435 {
436 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, DP) != 0;
437 }
438
isar_feature_aa64_fhm(const ARMISARegisters * id)439 static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
440 {
441 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, FHM) != 0;
442 }
443
isar_feature_aa64_condm_4(const ARMISARegisters * id)444 static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
445 {
446 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) != 0;
447 }
448
isar_feature_aa64_condm_5(const ARMISARegisters * id)449 static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
450 {
451 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) >= 2;
452 }
453
isar_feature_aa64_rndr(const ARMISARegisters * id)454 static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id)
455 {
456 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RNDR) != 0;
457 }
458
isar_feature_aa64_tlbirange(const ARMISARegisters * id)459 static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
460 {
461 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) == 2;
462 }
463
isar_feature_aa64_tlbios(const ARMISARegisters * id)464 static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
465 {
466 return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) != 0;
467 }
468
isar_feature_aa64_jscvt(const ARMISARegisters * id)469 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
470 {
471 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, JSCVT) != 0;
472 }
473
isar_feature_aa64_fcma(const ARMISARegisters * id)474 static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
475 {
476 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FCMA) != 0;
477 }
478
isar_feature_aa64_xs(const ARMISARegisters * id)479 static inline bool isar_feature_aa64_xs(const ARMISARegisters *id)
480 {
481 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, XS) != 0;
482 }
483
484 /*
485 * These are the values from APA/API/APA3.
486 * In general these must be compared '>=', per the normal Arm ARM
487 * treatment of fields in ID registers.
488 */
489 typedef enum {
490 PauthFeat_None = 0,
491 PauthFeat_1 = 1,
492 PauthFeat_EPAC = 2,
493 PauthFeat_2 = 3,
494 PauthFeat_FPAC = 4,
495 PauthFeat_FPACCOMBINED = 5,
496 } ARMPauthFeature;
497
498 static inline ARMPauthFeature
isar_feature_pauth_feature(const ARMISARegisters * id)499 isar_feature_pauth_feature(const ARMISARegisters *id)
500 {
501 /*
502 * Architecturally, only one of {APA,API,APA3} may be active (non-zero)
503 * and the other two must be zero. Thus we may avoid conditionals.
504 */
505 return (FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) |
506 FIELD_EX64_IDREG(id, ID_AA64ISAR1, API) |
507 FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3));
508 }
509
isar_feature_aa64_pauth(const ARMISARegisters * id)510 static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
511 {
512 /*
513 * Return true if any form of pauth is enabled, as this
514 * predicate controls migration of the 128-bit keys.
515 */
516 return isar_feature_pauth_feature(id) != PauthFeat_None;
517 }
518
isar_feature_aa64_pauth_qarma5(const ARMISARegisters * id)519 static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id)
520 {
521 /*
522 * Return true if pauth is enabled with the architected QARMA5 algorithm.
523 * QEMU will always enable or disable both APA and GPA.
524 */
525 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) != 0;
526 }
527
isar_feature_aa64_pauth_qarma3(const ARMISARegisters * id)528 static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id)
529 {
530 /*
531 * Return true if pauth is enabled with the architected QARMA3 algorithm.
532 * QEMU will always enable or disable both APA3 and GPA3.
533 */
534 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3) != 0;
535 }
536
isar_feature_aa64_sb(const ARMISARegisters * id)537 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
538 {
539 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SB) != 0;
540 }
541
isar_feature_aa64_predinv(const ARMISARegisters * id)542 static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
543 {
544 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SPECRES) != 0;
545 }
546
isar_feature_aa64_frint(const ARMISARegisters * id)547 static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
548 {
549 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FRINTTS) != 0;
550 }
551
isar_feature_aa64_dcpop(const ARMISARegisters * id)552 static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
553 {
554 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) != 0;
555 }
556
isar_feature_aa64_dcpodp(const ARMISARegisters * id)557 static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
558 {
559 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) >= 2;
560 }
561
isar_feature_aa64_bf16(const ARMISARegisters * id)562 static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id)
563 {
564 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) != 0;
565 }
566
isar_feature_aa64_ebf16(const ARMISARegisters * id)567 static inline bool isar_feature_aa64_ebf16(const ARMISARegisters *id)
568 {
569 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) > 1;
570 }
571
isar_feature_aa64_rcpc_8_3(const ARMISARegisters * id)572 static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
573 {
574 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) != 0;
575 }
576
isar_feature_aa64_rcpc_8_4(const ARMISARegisters * id)577 static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
578 {
579 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) >= 2;
580 }
581
isar_feature_aa64_i8mm(const ARMISARegisters * id)582 static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
583 {
584 return FIELD_EX64_IDREG(id, ID_AA64ISAR1, I8MM) != 0;
585 }
586
isar_feature_aa64_wfxt(const ARMISARegisters * id)587 static inline bool isar_feature_aa64_wfxt(const ARMISARegisters *id)
588 {
589 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, WFXT) >= 2;
590 }
591
isar_feature_aa64_hbc(const ARMISARegisters * id)592 static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
593 {
594 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0;
595 }
596
isar_feature_aa64_mops(const ARMISARegisters * id)597 static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
598 {
599 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS);
600 }
601
isar_feature_aa64_rpres(const ARMISARegisters * id)602 static inline bool isar_feature_aa64_rpres(const ARMISARegisters *id)
603 {
604 return FIELD_EX64_IDREG(id, ID_AA64ISAR2, RPRES);
605 }
606
isar_feature_aa64_fp_simd(const ARMISARegisters * id)607 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
608 {
609 /* We always set the AdvSIMD and FP fields identically. */
610 return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) != 0xf;
611 }
612
isar_feature_aa64_fp16(const ARMISARegisters * id)613 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
614 {
615 /* We always set the AdvSIMD and FP fields identically wrt FP16. */
616 return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) == 1;
617 }
618
isar_feature_aa64_aa32(const ARMISARegisters * id)619 static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
620 {
621 return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL0) >= 2;
622 }
623
isar_feature_aa64_aa32_el1(const ARMISARegisters * id)624 static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
625 {
626 return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL1) >= 2;
627 }
628
isar_feature_aa64_aa32_el2(const ARMISARegisters * id)629 static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
630 {
631 return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL2) >= 2;
632 }
633
isar_feature_aa64_ras(const ARMISARegisters * id)634 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
635 {
636 return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) != 0;
637 }
638
isar_feature_aa64_doublefault(const ARMISARegisters * id)639 static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id)
640 {
641 return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) >= 2;
642 }
643
isar_feature_aa64_sve(const ARMISARegisters * id)644 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
645 {
646 return FIELD_EX64_IDREG(id, ID_AA64PFR0, SVE) != 0;
647 }
648
isar_feature_aa64_sel2(const ARMISARegisters * id)649 static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
650 {
651 return FIELD_EX64_IDREG(id, ID_AA64PFR0, SEL2) != 0;
652 }
653
isar_feature_aa64_rme(const ARMISARegisters * id)654 static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
655 {
656 return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) != 0;
657 }
658
isar_feature_aa64_dit(const ARMISARegisters * id)659 static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
660 {
661 return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0;
662 }
663
isar_feature_aa64_scxtnum(const ARMISARegisters * id)664 static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
665 {
666 int key = FIELD_EX64_IDREG(id, ID_AA64PFR0, CSV2);
667 if (key >= 2) {
668 return true; /* FEAT_CSV2_2 */
669 }
670 if (key == 1) {
671 key = FIELD_EX64_IDREG(id, ID_AA64PFR1, CSV2_FRAC);
672 return key >= 2; /* FEAT_CSV2_1p2 */
673 }
674 return false;
675 }
676
isar_feature_aa64_ssbs(const ARMISARegisters * id)677 static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
678 {
679 return FIELD_EX64_IDREG(id, ID_AA64PFR1, SSBS) != 0;
680 }
681
isar_feature_aa64_bti(const ARMISARegisters * id)682 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
683 {
684 return FIELD_EX64_IDREG(id, ID_AA64PFR1, BT) != 0;
685 }
686
isar_feature_aa64_mte_insn_reg(const ARMISARegisters * id)687 static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id)
688 {
689 return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) != 0;
690 }
691
isar_feature_aa64_mte(const ARMISARegisters * id)692 static inline bool isar_feature_aa64_mte(const ARMISARegisters *id)
693 {
694 return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 2;
695 }
696
isar_feature_aa64_mte3(const ARMISARegisters * id)697 static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id)
698 {
699 return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 3;
700 }
701
isar_feature_aa64_sme(const ARMISARegisters * id)702 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
703 {
704 return FIELD_EX64_IDREG(id, ID_AA64PFR1, SME) != 0;
705 }
706
isar_feature_aa64_nmi(const ARMISARegisters * id)707 static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
708 {
709 return FIELD_EX64_IDREG(id, ID_AA64PFR1, NMI) != 0;
710 }
711
isar_feature_aa64_tgran4_lpa2(const ARMISARegisters * id)712 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
713 {
714 return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1;
715 }
716
isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters * id)717 static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id)
718 {
719 unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2);
720 return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id));
721 }
722
isar_feature_aa64_tgran16_lpa2(const ARMISARegisters * id)723 static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id)
724 {
725 return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 2;
726 }
727
isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters * id)728 static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
729 {
730 unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2);
731 return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
732 }
733
isar_feature_aa64_tgran4(const ARMISARegisters * id)734 static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
735 {
736 return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 0;
737 }
738
isar_feature_aa64_tgran16(const ARMISARegisters * id)739 static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
740 {
741 return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 1;
742 }
743
isar_feature_aa64_tgran64(const ARMISARegisters * id)744 static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
745 {
746 return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN64) >= 0;
747 }
748
isar_feature_aa64_tgran4_2(const ARMISARegisters * id)749 static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
750 {
751 unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2);
752 return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
753 }
754
isar_feature_aa64_tgran16_2(const ARMISARegisters * id)755 static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
756 {
757 unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2);
758 return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
759 }
760
isar_feature_aa64_tgran64_2(const ARMISARegisters * id)761 static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
762 {
763 unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN64_2);
764 return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
765 }
766
isar_feature_aa64_fgt(const ARMISARegisters * id)767 static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
768 {
769 return FIELD_EX64_IDREG(id, ID_AA64MMFR0, FGT) != 0;
770 }
771
isar_feature_aa64_ecv_traps(const ARMISARegisters * id)772 static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
773 {
774 return FIELD_EX64_IDREG(id, ID_AA64MMFR0, ECV) > 0;
775 }
776
isar_feature_aa64_ecv(const ARMISARegisters * id)777 static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
778 {
779 return FIELD_EX64_IDREG(id, ID_AA64MMFR0, ECV) > 1;
780 }
781
isar_feature_aa64_vh(const ARMISARegisters * id)782 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
783 {
784 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, VH) != 0;
785 }
786
isar_feature_aa64_lor(const ARMISARegisters * id)787 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
788 {
789 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, LO) != 0;
790 }
791
isar_feature_aa64_pan(const ARMISARegisters * id)792 static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
793 {
794 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) != 0;
795 }
796
isar_feature_aa64_ats1e1(const ARMISARegisters * id)797 static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
798 {
799 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 2;
800 }
801
isar_feature_aa64_pan3(const ARMISARegisters * id)802 static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
803 {
804 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 3;
805 }
806
isar_feature_aa64_hcx(const ARMISARegisters * id)807 static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
808 {
809 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HCX) != 0;
810 }
811
isar_feature_aa64_afp(const ARMISARegisters * id)812 static inline bool isar_feature_aa64_afp(const ARMISARegisters *id)
813 {
814 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, AFP) != 0;
815 }
816
isar_feature_aa64_tidcp1(const ARMISARegisters * id)817 static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
818 {
819 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, TIDCP1) != 0;
820 }
821
isar_feature_aa64_cmow(const ARMISARegisters * id)822 static inline bool isar_feature_aa64_cmow(const ARMISARegisters *id)
823 {
824 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, CMOW) != 0;
825 }
826
isar_feature_aa64_hafs(const ARMISARegisters * id)827 static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
828 {
829 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) != 0;
830 }
831
isar_feature_aa64_hdbs(const ARMISARegisters * id)832 static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id)
833 {
834 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) >= 2;
835 }
836
isar_feature_aa64_tts2uxn(const ARMISARegisters * id)837 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
838 {
839 return FIELD_EX64_IDREG(id, ID_AA64MMFR1, XNX) != 0;
840 }
841
isar_feature_aa64_uao(const ARMISARegisters * id)842 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
843 {
844 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, UAO) != 0;
845 }
846
isar_feature_aa64_st(const ARMISARegisters * id)847 static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
848 {
849 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, ST) != 0;
850 }
851
isar_feature_aa64_lse2(const ARMISARegisters * id)852 static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
853 {
854 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, AT) != 0;
855 }
856
isar_feature_aa64_fwb(const ARMISARegisters * id)857 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
858 {
859 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, FWB) != 0;
860 }
861
isar_feature_aa64_ids(const ARMISARegisters * id)862 static inline bool isar_feature_aa64_ids(const ARMISARegisters *id)
863 {
864 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, IDS) != 0;
865 }
866
isar_feature_aa64_half_evt(const ARMISARegisters * id)867 static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id)
868 {
869 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 1;
870 }
871
isar_feature_aa64_evt(const ARMISARegisters * id)872 static inline bool isar_feature_aa64_evt(const ARMISARegisters *id)
873 {
874 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 2;
875 }
876
isar_feature_aa64_ccidx(const ARMISARegisters * id)877 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
878 {
879 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, CCIDX) != 0;
880 }
881
isar_feature_aa64_lva(const ARMISARegisters * id)882 static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
883 {
884 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, VARANGE) != 0;
885 }
886
isar_feature_aa64_e0pd(const ARMISARegisters * id)887 static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
888 {
889 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, E0PD) != 0;
890 }
891
isar_feature_aa64_nv(const ARMISARegisters * id)892 static inline bool isar_feature_aa64_nv(const ARMISARegisters *id)
893 {
894 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) != 0;
895 }
896
isar_feature_aa64_nv2(const ARMISARegisters * id)897 static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
898 {
899 return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) >= 2;
900 }
901
isar_feature_aa64_pmuv3p1(const ARMISARegisters * id)902 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
903 {
904 return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 &&
905 FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
906 }
907
isar_feature_aa64_pmuv3p4(const ARMISARegisters * id)908 static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id)
909 {
910 return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 5 &&
911 FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
912 }
913
isar_feature_aa64_pmuv3p5(const ARMISARegisters * id)914 static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id)
915 {
916 return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 6 &&
917 FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
918 }
919
isar_feature_aa64_debugv8p2(const ARMISARegisters * id)920 static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
921 {
922 return FIELD_EX64_IDREG(id, ID_AA64DFR0, DEBUGVER) >= 8;
923 }
924
isar_feature_aa64_doublelock(const ARMISARegisters * id)925 static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
926 {
927 return FIELD_SEX64_IDREG(id, ID_AA64DFR0, DOUBLELOCK) >= 0;
928 }
929
isar_feature_aa64_sve2(const ARMISARegisters * id)930 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
931 {
932 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SVEVER) != 0;
933 }
934
isar_feature_aa64_sve2_aes(const ARMISARegisters * id)935 static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id)
936 {
937 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) != 0;
938 }
939
isar_feature_aa64_sve2_pmull128(const ARMISARegisters * id)940 static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id)
941 {
942 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 2;
943 }
944
isar_feature_aa64_sve2_bitperm(const ARMISARegisters * id)945 static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id)
946 {
947 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0;
948 }
949
isar_feature_aa64_sve_bf16(const ARMISARegisters * id)950 static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id)
951 {
952 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BFLOAT16) != 0;
953 }
954
isar_feature_aa64_sve2_sha3(const ARMISARegisters * id)955 static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id)
956 {
957 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SHA3) != 0;
958 }
959
isar_feature_aa64_sve2_sm4(const ARMISARegisters * id)960 static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id)
961 {
962 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SM4) != 0;
963 }
964
isar_feature_aa64_sve_i8mm(const ARMISARegisters * id)965 static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
966 {
967 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, I8MM) != 0;
968 }
969
isar_feature_aa64_sve_f32mm(const ARMISARegisters * id)970 static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id)
971 {
972 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F32MM) != 0;
973 }
974
isar_feature_aa64_sve_f64mm(const ARMISARegisters * id)975 static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
976 {
977 return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F64MM) != 0;
978 }
979
isar_feature_aa64_sme_f64f64(const ARMISARegisters * id)980 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id)
981 {
982 return FIELD_EX64_IDREG(id, ID_AA64SMFR0, F64F64);
983 }
984
isar_feature_aa64_sme_i16i64(const ARMISARegisters * id)985 static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id)
986 {
987 return FIELD_EX64_IDREG(id, ID_AA64SMFR0, I16I64) == 0xf;
988 }
989
isar_feature_aa64_sme_fa64(const ARMISARegisters * id)990 static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id)
991 {
992 return FIELD_EX64_IDREG(id, ID_AA64SMFR0, FA64);
993 }
994
995 /*
996 * Feature tests for "does this exist in either 32-bit or 64-bit?"
997 */
isar_feature_any_fp16(const ARMISARegisters * id)998 static inline bool isar_feature_any_fp16(const ARMISARegisters *id)
999 {
1000 return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id);
1001 }
1002
isar_feature_any_predinv(const ARMISARegisters * id)1003 static inline bool isar_feature_any_predinv(const ARMISARegisters *id)
1004 {
1005 return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id);
1006 }
1007
isar_feature_any_pmuv3p1(const ARMISARegisters * id)1008 static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id)
1009 {
1010 return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id);
1011 }
1012
isar_feature_any_pmuv3p4(const ARMISARegisters * id)1013 static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id)
1014 {
1015 return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id);
1016 }
1017
isar_feature_any_pmuv3p5(const ARMISARegisters * id)1018 static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id)
1019 {
1020 return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id);
1021 }
1022
isar_feature_any_ccidx(const ARMISARegisters * id)1023 static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
1024 {
1025 return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
1026 }
1027
isar_feature_any_tts2uxn(const ARMISARegisters * id)1028 static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
1029 {
1030 return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
1031 }
1032
isar_feature_any_debugv8p2(const ARMISARegisters * id)1033 static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
1034 {
1035 return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
1036 }
1037
isar_feature_any_ras(const ARMISARegisters * id)1038 static inline bool isar_feature_any_ras(const ARMISARegisters *id)
1039 {
1040 return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
1041 }
1042
isar_feature_any_half_evt(const ARMISARegisters * id)1043 static inline bool isar_feature_any_half_evt(const ARMISARegisters *id)
1044 {
1045 return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id);
1046 }
1047
isar_feature_any_evt(const ARMISARegisters * id)1048 static inline bool isar_feature_any_evt(const ARMISARegisters *id)
1049 {
1050 return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id);
1051 }
1052
1053 typedef enum {
1054 CCSIDR_FORMAT_LEGACY,
1055 CCSIDR_FORMAT_CCIDX,
1056 } CCSIDRFormat;
1057
make_ccsidr(CCSIDRFormat format,unsigned assoc,unsigned linesize,unsigned cachesize,uint8_t flags)1058 static inline uint64_t make_ccsidr(CCSIDRFormat format, unsigned assoc,
1059 unsigned linesize, unsigned cachesize,
1060 uint8_t flags)
1061 {
1062 unsigned lg_linesize = ctz32(linesize);
1063 unsigned sets;
1064 uint64_t ccsidr = 0;
1065
1066 assert(assoc != 0);
1067 assert(is_power_of_2(linesize));
1068 assert(lg_linesize >= 4 && lg_linesize <= 7 + 4);
1069
1070 /* sets * associativity * linesize == cachesize. */
1071 sets = cachesize / (assoc * linesize);
1072 assert(cachesize % (assoc * linesize) == 0);
1073
1074 if (format == CCSIDR_FORMAT_LEGACY) {
1075 /*
1076 * The 32-bit CCSIDR format is:
1077 * [27:13] number of sets - 1
1078 * [12:3] associativity - 1
1079 * [2:0] log2(linesize) - 4
1080 * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
1081 */
1082 ccsidr = deposit32(ccsidr, 28, 4, flags);
1083 ccsidr = deposit32(ccsidr, 13, 15, sets - 1);
1084 ccsidr = deposit32(ccsidr, 3, 10, assoc - 1);
1085 ccsidr = deposit32(ccsidr, 0, 3, lg_linesize - 4);
1086 } else {
1087 /*
1088 * The 64-bit CCSIDR_EL1 format is:
1089 * [55:32] number of sets - 1
1090 * [23:3] associativity - 1
1091 * [2:0] log2(linesize) - 4
1092 * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
1093 */
1094 ccsidr = deposit64(ccsidr, 32, 24, sets - 1);
1095 ccsidr = deposit64(ccsidr, 3, 21, assoc - 1);
1096 ccsidr = deposit64(ccsidr, 0, 3, lg_linesize - 4);
1097 }
1098
1099 return ccsidr;
1100 }
1101
1102 /*
1103 * Forward to the above feature tests given an ARMCPU pointer.
1104 */
1105 #define cpu_isar_feature(name, cpu) \
1106 ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
1107
1108 #endif
1109