aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/arch/aarch64/cpu_flags.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linux-generic/arch/aarch64/cpu_flags.c')
-rw-r--r--platform/linux-generic/arch/aarch64/cpu_flags.c976
1 files changed, 976 insertions, 0 deletions
diff --git a/platform/linux-generic/arch/aarch64/cpu_flags.c b/platform/linux-generic/arch/aarch64/cpu_flags.c
new file mode 100644
index 000000000..d70e26271
--- /dev/null
+++ b/platform/linux-generic/arch/aarch64/cpu_flags.c
@@ -0,0 +1,976 @@
+/* Copyright (c) 2018, Linaro Limited
+ * Copyright (c) 2020-2021, Nokia
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <asm/hwcap.h>
+
+#include <odp/api/hints.h>
+#include <odp_debug_internal.h>
+#include "cpu_flags.h"
+
+typedef struct {
+ const char *feat_flag;
+ const unsigned int hwcap_field;
+ bool valid;
+} hwcap_feat_flag_t;
+
+static hwcap_feat_flag_t hwcap_flags[] = {
+ {
+ /* Floating-point Extensions */
+ .feat_flag = "FEAT_FP",
+#ifdef HWCAP_FP
+ .hwcap_field = HWCAP_FP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Floating-point Extensions */
+ .feat_flag = "FEAT_FP",
+#ifdef HWCAP_ASIMD
+ .hwcap_field = HWCAP_ASIMD,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Generic Timer is configured to generate events at approx. 10KHz */
+ .feat_flag = "HWCAP_EVTSTRM",
+#ifdef HWCAP_EVTSTRM
+ .hwcap_field = HWCAP_EVTSTRM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD AES Instructions */
+ .feat_flag = "FEAT_AES",
+#ifdef HWCAP_AES
+ .hwcap_field = HWCAP_AES,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD PMULL Instructions */
+ .feat_flag = "FEAT_PMULL",
+#ifdef HWCAP_PMULL
+ .hwcap_field = HWCAP_PMULL,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD SHA1 Instructions */
+ .feat_flag = "FEAT_SHA1",
+#ifdef HWCAP_SHA1
+ .hwcap_field = HWCAP_SHA1,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD SHA256 Instructions */
+ .feat_flag = "FEAT_SHA256",
+#ifdef HWCAP_SHA2
+ .hwcap_field = HWCAP_SHA2,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* CRC32 Instructions */
+ .feat_flag = "FEAT_CRC32",
+#ifdef HWCAP_CRC32
+ .hwcap_field = HWCAP_CRC32,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Large System Extensions */
+ .feat_flag = "FEAT_LSE",
+#ifdef HWCAP_ATOMICS
+ .hwcap_field = HWCAP_ATOMICS,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Half-precision Floating-point Data Processing Instructions */
+ .feat_flag = "FEAT_FP16",
+#ifdef HWCAP_FPHP
+ .hwcap_field = HWCAP_FPHP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Half-precision Floating-point Data Processing Instructions */
+ .feat_flag = "FEAT_FP16",
+#ifdef HWCAP_ASIMDHP
+ .hwcap_field = HWCAP_ASIMDHP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Availability of EL0 Access to certain ID Registers */
+ .feat_flag = "HWCAP_CPUID",
+#ifdef HWCAP_CPUID
+ .hwcap_field = HWCAP_CPUID,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Rounding Double Multiply Accumulate Extensions */
+ .feat_flag = "FEAT_RDM",
+#ifdef HWCAP_ASIMDRDM
+ .hwcap_field = HWCAP_ASIMDRDM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* JavaScript FJCVTS Conversion Instructions */
+ .feat_flag = "FEAT_JSCVT",
+#ifdef HWCAP_JSCVT
+ .hwcap_field = HWCAP_JSCVT,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Floating-point FCMLA and FCADD Instructions */
+ .feat_flag = "FEAT_FCMA",
+#ifdef HWCAP_FCMA
+ .hwcap_field = HWCAP_FCMA,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Load-acquire RCpc Instructions */
+ .feat_flag = "FEAT_LRCPC",
+#ifdef HWCAP_LRCPC
+ .hwcap_field = HWCAP_LRCPC,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* DC CVAP Instructions */
+ .feat_flag = "FEAT_DPB",
+#ifdef HWCAP_DCPOP
+ .hwcap_field = HWCAP_DCPOP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD EOR3, RAX1, XAR, and BCAX Instructions */
+ .feat_flag = "FEAT_SHA3",
+#ifdef HWCAP_SHA3
+ .hwcap_field = HWCAP_SHA3,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD SM3 Instructions */
+ .feat_flag = "FEAT_SM3",
+#ifdef HWCAP_SM3
+ .hwcap_field = HWCAP_SM3,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD SM4 Instructions */
+ .feat_flag = "FEAT_SM4",
+#ifdef HWCAP_SM4
+ .hwcap_field = HWCAP_SM4,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD Int8 Dot Product Instructions */
+ .feat_flag = "FEAT_DotProd",
+#ifdef HWCAP_ASIMDDP
+ .hwcap_field = HWCAP_ASIMDDP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD SHA512 Instructions */
+ .feat_flag = "FEAT_SHA512",
+#ifdef HWCAP_SHA512
+ .hwcap_field = HWCAP_SHA512,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Scalable Vector Extensions */
+ .feat_flag = "FEAT_SVE",
+#ifdef HWCAP_SVE
+ .hwcap_field = HWCAP_SVE,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Half-precision Floating-point FMLAL Instructions */
+ .feat_flag = "FEAT_FHM",
+#ifdef HWCAP_ASIMDFHM
+ .hwcap_field = HWCAP_ASIMDFHM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Data Independent Timing Instructions */
+ .feat_flag = "FEAT_DIT",
+#ifdef HWCAP_DIT
+ .hwcap_field = HWCAP_DIT,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Large System Extensions Version 2 */
+ .feat_flag = "FEAT_LSE2",
+#ifdef HWCAP_USCAT
+ .hwcap_field = HWCAP_USCAT,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Load-acquire RCpc Instructions Version 2 */
+ .feat_flag = "FEAT_LRCPC2",
+#ifdef HWCAP_ILRCPC
+ .hwcap_field = HWCAP_ILRCPC,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Condition Flag Manipulation Extensions */
+ .feat_flag = "FEAT_FlagM",
+#ifdef HWCAP_FLAGM
+ .hwcap_field = HWCAP_FLAGM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Speculative Store Bypass Safe Instructions */
+ .feat_flag = "FEAT_SSBS2",
+#ifdef HWCAP_SSBS
+ .hwcap_field = HWCAP_SSBS,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Speculation Barrier Instructions */
+ .feat_flag = "FEAT_SB",
+#ifdef HWCAP_SB
+ .hwcap_field = HWCAP_SB,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Pointer Authentication Extensions */
+ .feat_flag = "FEAT_PAuth",
+#ifdef HWCAP_PACA
+ .hwcap_field = HWCAP_PACA,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Generic Authentication Extensions */
+ .feat_flag = "HWCAP_PACG",
+#ifdef HWCAP_PACG
+ .hwcap_field = HWCAP_PACG,
+ .valid = 1,
+#endif
+ }
+};
+
+static hwcap_feat_flag_t hwcap2_flags[] = {
+ {
+ /* DC CVADP instructions */
+ .feat_flag = "FEAT_DPB2",
+#ifdef HWCAP2_DCPODP
+ .hwcap_field = HWCAP2_DCPODP,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Scalable Vector Extensions Version 2 */
+ .feat_flag = "FEAT_SVE2",
+#ifdef HWCAP2_SVE2
+ .hwcap_field = HWCAP2_SVE2,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE AES Instructions */
+ .feat_flag = "FEAT_SVE_AES",
+#ifdef HWCAP2_SVEAES
+ .hwcap_field = HWCAP2_SVEAES,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE PMULL Instructions */
+ .feat_flag = "FEAT_SVE_PMULL128",
+#ifdef HWCAP2_SVEPMULL
+ .hwcap_field = HWCAP2_SVEPMULL,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE Bit Permute Instructions */
+ .feat_flag = "FEAT_SVE_BitPerm",
+#ifdef HWCAP2_SVEBITPERM
+ .hwcap_field = HWCAP2_SVEBITPERM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE SHA-3 Instructions */
+ .feat_flag = "FEAT_SVE_SHA3",
+#ifdef HWCAP2_SVESHA3
+ .hwcap_field = HWCAP2_SVESHA3,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE SM4 Instructions */
+ .feat_flag = "FEAT_SVE_SM4",
+#ifdef HWCAP2_SVESM4
+ .hwcap_field = HWCAP2_SVESM4,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Condition Flag Manipulation Extensions Version 2 */
+ .feat_flag = "FEAT_FlagM2",
+#ifdef HWCAP2_FLAGM2
+ .hwcap_field = HWCAP2_FLAGM2,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* FRINT32Z, FRINT32X, FRINT64Z, and FRINT64X instructions */
+ .feat_flag = "FEAT_FRINTTS",
+#ifdef HWCAP2_FRINT
+ .hwcap_field = HWCAP2_FRINT,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE Int8 Matrix Multiplication Instructions */
+ .feat_flag = "FEAT_I8MM",
+#ifdef HWCAP2_SVEI8MM
+ .hwcap_field = HWCAP2_SVEI8MM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE Single-precision Floating-point Matrix Multiply Instructions */
+ .feat_flag = "FEAT_F32MM",
+#ifdef HWCAP2_SVEF32MM
+ .hwcap_field = HWCAP2_SVEF32MM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE Double-precision Floating-point Matrix Multiply Instructions */
+ .feat_flag = "FEAT_F64MM",
+#ifdef HWCAP2_SVEF64MM
+ .hwcap_field = HWCAP2_SVEF64MM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* SVE BFloat16 Instructions */
+ .feat_flag = "FEAT_BF16",
+#ifdef HWCAP2_SVEBF16
+ .hwcap_field = HWCAP2_SVEBF16,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD and Floating-point Int8 Matrix Multiplication Instructions */
+ .feat_flag = "FEAT_I8MM",
+#ifdef HWCAP2_I8MM
+ .hwcap_field = HWCAP2_I8MM,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Advanced SIMD and Floating-point BFloat16 Instructions */
+ .feat_flag = "FEAT_BF16",
+#ifdef HWCAP2_BF16
+ .hwcap_field = HWCAP2_BF16,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Data Gathering Hint Extensions */
+ .feat_flag = "FEAT_DGH",
+#ifdef HWCAP2_DGH
+ .hwcap_field = HWCAP2_DGH,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Random Number Generation Extensions */
+ .feat_flag = "FEAT_RNG",
+#ifdef HWCAP2_RNG
+ .hwcap_field = HWCAP2_RNG,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Branch Target Identification Extensions */
+ .feat_flag = "FEAT_BTI",
+#ifdef HWCAP2_BTI
+ .hwcap_field = HWCAP2_BTI,
+ .valid = 1,
+#endif
+ },
+
+ {
+ /* Full Memory Tagging Extensions */
+ .feat_flag = "FEAT_MTE2",
+#ifdef HWCAP2_MTE
+ .hwcap_field = HWCAP2_MTE,
+ .valid = 1,
+#endif
+ }
+};
+
+static void _odp_sys_info_print_acle_flags(void)
+{
+ const char *ndef = "n/a";
+
+ /* Avoid compiler warning about unused variable */
+ (void)ndef;
+
+ /* See ARM C Language Extensions documentation for details */
+ ODP_PRINT("ARM FEATURES:\n");
+
+ ODP_PRINT(" __ARM_ALIGN_MAX_PWR ");
+#ifdef __ARM_ALIGN_MAX_PWR
+ ODP_PRINT("%i\n", __ARM_ALIGN_MAX_PWR);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_ALIGN_MAX_STACK_PWR ");
+#ifdef __ARM_ALIGN_MAX_STACK_PWR
+ ODP_PRINT("%i\n", __ARM_ALIGN_MAX_STACK_PWR);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_ARCH ");
+#ifdef __ARM_ARCH
+ ODP_PRINT("%i\n", __ARM_ARCH);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_ARCH_ISA_A64 ");
+#ifdef __ARM_ARCH_ISA_A64
+ ODP_PRINT("%i\n", __ARM_ARCH_ISA_A64);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_BIG_ENDIAN ");
+#ifdef __ARM_BIG_ENDIAN
+ ODP_PRINT("%i\n", __ARM_BIG_ENDIAN);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_BF16_FORMAT_ALTERNATIVE ");
+#ifdef __ARM_BF16_FORMAT_ALTERNATIVE
+ ODP_PRINT("%i\n", __ARM_BF16_FORMAT_ALTERNATIVE);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_ATOMICS ");
+#ifdef __ARM_FEATURE_ATOMICS
+ ODP_PRINT("%i\n", __ARM_FEATURE_ATOMICS);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_BF16 ");
+#ifdef __ARM_FEATURE_BF16
+ ODP_PRINT("%i\n", __ARM_FEATURE_BF16);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_BTI_DEFAULT ");
+#ifdef __ARM_FEATURE_BTI_DEFAULT
+ ODP_PRINT("%i\n", __ARM_FEATURE_BTI_DEFAULT);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_CDE ");
+#ifdef __ARM_FEATURE_CDE
+ ODP_PRINT("%i\n", __ARM_FEATURE_CDE);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_CDE_COPROC ");
+#ifdef __ARM_FEATURE_CDE_COPROC
+ ODP_PRINT("0x%X\n", __ARM_FEATURE_CDE_COPROC);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_CLZ ");
+#ifdef __ARM_FEATURE_CLZ
+ ODP_PRINT("%i\n", __ARM_FEATURE_CLZ);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_COMPLEX ");
+#ifdef __ARM_FEATURE_COMPLEX
+ ODP_PRINT("%i\n", __ARM_FEATURE_COMPLEX);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_COPROC ");
+#ifdef __ARM_FEATURE_COPROC
+ ODP_PRINT("0x%X\n", __ARM_FEATURE_COPROC);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_CRC32 ");
+#ifdef __ARM_FEATURE_CRC32
+ ODP_PRINT("%i\n", __ARM_FEATURE_CRC32);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_CRYPTO ");
+#ifdef __ARM_FEATURE_CRYPTO
+ ODP_PRINT("%i\n", __ARM_FEATURE_CRYPTO);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_DIRECTED_ROUNDING ");
+#ifdef __ARM_FEATURE_DIRECTED_ROUNDING
+ ODP_PRINT("%i\n", __ARM_FEATURE_DIRECTED_ROUNDING);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_DOTPROD ");
+#ifdef __ARM_FEATURE_DOTPROD
+ ODP_PRINT("%i\n", __ARM_FEATURE_DOTPROD);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_FMA ");
+#ifdef __ARM_FEATURE_FMA
+ ODP_PRINT("%i\n", __ARM_FEATURE_FMA);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_FP16_FML ");
+#ifdef __ARM_FEATURE_FP16_FML
+ ODP_PRINT("%i\n", __ARM_FEATURE_FP16_FML);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_FRINT ");
+#ifdef __ARM_FEATURE_FRINT
+ ODP_PRINT("%i\n", __ARM_FEATURE_FRINT);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_IDIV ");
+#ifdef __ARM_FEATURE_IDIV
+ ODP_PRINT("%i\n", __ARM_FEATURE_IDIV);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_JCVT ");
+#ifdef __ARM_FEATURE_JCVT
+ ODP_PRINT("%i\n", __ARM_FEATURE_JCVT);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_MATMUL_INT8 ");
+#ifdef __ARM_FEATURE_MATMUL_INT8
+ ODP_PRINT("%i\n", __ARM_FEATURE_MATMUL_INT8);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_MEMORY_TAGGING ");
+#ifdef __ARM_FEATURE_MEMORY_TAGGING
+ ODP_PRINT("%i\n", __ARM_FEATURE_MEMORY_TAGGING);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_MVE ");
+#ifdef __ARM_FEATURE_MVE
+ ODP_PRINT("0x%X\n", __ARM_FEATURE_MVE);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_NUMERIC_MAXMIN ");
+#ifdef __ARM_FEATURE_NUMERIC_MAXMIN
+ ODP_PRINT("%i\n", __ARM_FEATURE_NUMERIC_MAXMIN);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_PAC_DEFAULT ");
+#ifdef __ARM_FEATURE_PAC_DEFAULT
+ ODP_PRINT("0x%X\n", __ARM_FEATURE_PAC_DEFAULT);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_QRDMX ");
+#ifdef __ARM_FEATURE_QRDMX
+ ODP_PRINT("%i\n", __ARM_FEATURE_QRDMX);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_RNG ");
+#ifdef __ARM_FEATURE_RNG
+ ODP_PRINT("%i\n", __ARM_FEATURE_RNG);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_SHA3 ");
+#ifdef __ARM_FEATURE_SHA3
+ ODP_PRINT("%i\n", __ARM_FEATURE_SHA3);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_SHA512 ");
+#ifdef __ARM_FEATURE_SHA512
+ ODP_PRINT("%i\n", __ARM_FEATURE_SHA512);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_SM3 ");
+#ifdef __ARM_FEATURE_SM3
+ ODP_PRINT("%i\n", __ARM_FEATURE_SM3);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_SM4 ");
+#ifdef __ARM_FEATURE_SM4
+ ODP_PRINT("%i\n", __ARM_FEATURE_SM4);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_TME ");
+#ifdef __ARM_FEATURE_TME
+ ODP_PRINT("%i\n", __ARM_FEATURE_TME);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FEATURE_UNALIGNED ");
+#ifdef __ARM_FEATURE_UNALIGNED
+ ODP_PRINT("%i\n", __ARM_FEATURE_UNALIGNED);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP ");
+#ifdef __ARM_FP
+ ODP_PRINT("0x%X\n", __ARM_FP);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP_FAST ");
+#ifdef __ARM_FP_FAST
+ ODP_PRINT("%i\n", __ARM_FP_FAST);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP_FENV_ROUNDING ");
+#ifdef __ARM_FP_FENV_ROUNDING
+ ODP_PRINT("%i\n", __ARM_FP_FENV_ROUNDING);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP16_ARGS ");
+#ifdef __ARM_FP16_ARGS
+ ODP_PRINT("%i\n", __ARM_FP16_ARGS);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP16_FORMAT_ALTERNATIVE ");
+#ifdef __ARM_FP16_FORMAT_ALTERNATIVE
+ ODP_PRINT("%i\n", __ARM_FP16_FORMAT_ALTERNATIVE);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_FP16_FORMAT_IEEE ");
+#ifdef __ARM_FP16_FORMAT_IEEE
+ ODP_PRINT("%i\n", __ARM_FP16_FORMAT_IEEE);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_NEON ");
+#ifdef __ARM_NEON
+ ODP_PRINT("%i\n", __ARM_NEON);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_NEON_FP ");
+#ifdef __ARM_NEON_FP
+ ODP_PRINT("0x%X\n", __ARM_NEON_FP);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_PCS_AAPCS64 ");
+#ifdef __ARM_PCS_AAPCS64
+ ODP_PRINT("%i\n", __ARM_PCS_AAPCS64);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_ROPI ");
+#ifdef __ARM_ROPI
+ ODP_PRINT("%i\n", __ARM_ROPI);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_RWPI ");
+#ifdef __ARM_RWPI
+ ODP_PRINT("%i\n", __ARM_RWPI);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_SIZEOF_MINIMAL_ENUM ");
+#ifdef __ARM_SIZEOF_MINIMAL_ENUM
+ ODP_PRINT("%i\n", __ARM_SIZEOF_MINIMAL_ENUM);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" __ARM_SIZEOF_WCHAR_T ");
+#ifdef __ARM_SIZEOF_WCHAR_T
+ ODP_PRINT("%i\n", __ARM_SIZEOF_WCHAR_T);
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT(" ARM ISA version: ");
+#if defined(__ARM_ARCH)
+ if (__ARM_ARCH < 8) {
+ ODP_PRINT("v%i\n", __ARM_ARCH);
+ } else if (__ARM_ARCH == 8) {
+ /* Actually, this checks for new NEON instructions in
+ * v8.1, but is currently the only way to distinguish
+ * v8.0 and >=v8.1. */
+ #ifdef __ARM_FEATURE_QRDMX
+ ODP_PRINT("v8.1 or higher\n");
+ #else
+ ODP_PRINT("v8.0\n");
+ #endif
+ } else {
+ /* ACLE 2018 defines that from v8.1 onwards the value includes
+ * the minor version number: __ARM_ARCH = X * 100 + Y
+ * E.g. for Armv8.1 __ARM_ARCH = 801 */
+ int major = __ARM_ARCH / 100;
+ int minor = __ARM_ARCH - (major * 100);
+
+ ODP_PRINT("v%i.%i\n", major, minor);
+ }
+#else
+ ODP_PRINT("%s\n", ndef);
+#endif
+
+ ODP_PRINT("\n");
+}
+
+static int check_hwcap_duplicates(unsigned int hwcap_field)
+{
+ int ret = 0;
+
+ /* FP and AdvSIMD fields of the AArch64 Processor
+ * Feature Register 0 must have the same value and are
+ * defined by the same feature flag. Print the flag
+ * only once. */
+#ifdef HWCAP_ASIMD
+ if (hwcap_field == HWCAP_ASIMD)
+ ret = 1;
+#endif
+#ifdef HWCAP_ASIMDHP
+ if (hwcap_field == HWCAP_ASIMDHP)
+ ret = 1;
+#endif
+
+ return ret;
+}
+
+static void _odp_sys_info_print_hwcap_flags(void)
+{
+ unsigned long hwcaps, hwcaps2;
+ unsigned int size, size2;
+
+ ODP_PRINT("ARM FEATURES SUPPORTED BY HARDWARE:\n");
+
+ /* Print supported hardware flags via AT_HWCAP entry of the hwcaps
+ * auxiliary vector. */
+ hwcaps = getauxval(AT_HWCAP);
+ size = sizeof(hwcap_flags) / sizeof(hwcap_feat_flag_t);
+ for (unsigned int i = 0; i < size; i++) {
+ if (hwcap_flags[i].valid) {
+ if (check_hwcap_duplicates(hwcap_flags[i].hwcap_field)) {
+ hwcaps = hwcaps >> 1;
+ continue;
+ }
+
+ if (hwcaps & 0x01)
+ ODP_PRINT("%s ", hwcap_flags[i].feat_flag);
+ hwcaps = hwcaps >> 1;
+ }
+ }
+
+ /* Print supported hardware flags via AT_HWCAP2 entry of the hwcaps
+ * auxiliary vector. */
+ hwcaps2 = getauxval(AT_HWCAP2);
+ size2 = sizeof(hwcap2_flags) / sizeof(hwcap_feat_flag_t);
+ for (unsigned long i = 0; i < size2; i++) {
+ if (hwcap2_flags[i].valid) {
+ if (hwcaps2 & 0x01)
+ ODP_PRINT("%s ", hwcap2_flags[i].feat_flag);
+ hwcaps2 = hwcaps2 >> 1;
+ }
+ }
+
+ ODP_PRINT("\n");
+
+ /* Re-initialize hwcaps and hwcaps2 */
+ hwcaps = 0;
+ hwcaps2 = 0;
+
+ ODP_PRINT("\nARM FEATURES NOT SUPPORTED BY HARDWARE:\n");
+
+ hwcaps = getauxval(AT_HWCAP);
+ for (unsigned long i = 0; i < size; i++) {
+ if (hwcap_flags[i].valid) {
+ if (check_hwcap_duplicates(hwcap_flags[i].hwcap_field)) {
+ hwcaps = hwcaps >> 1;
+ continue;
+ }
+
+ if (!(hwcaps & 0x01))
+ ODP_PRINT("%s ", hwcap_flags[i].feat_flag);
+ hwcaps = hwcaps >> 1;
+ }
+ }
+
+ hwcaps2 = getauxval(AT_HWCAP2);
+ for (unsigned long i = 0; i < size2; i++) {
+ if (hwcap2_flags[i].valid) {
+ if (!(hwcaps2 & 0x01))
+ ODP_PRINT("%s ", hwcap2_flags[i].feat_flag);
+ hwcaps2 = hwcaps2 >> 1;
+ }
+ }
+
+ ODP_PRINT("\n");
+
+ ODP_PRINT("\nARM FEATURES NOT SUPPORTED BY KERNEL:\n");
+
+ for (unsigned long i = 0; i < size; i++) {
+ if (!hwcap_flags[i].valid)
+ ODP_PRINT("%s ", hwcap_flags[i].feat_flag);
+ }
+
+ for (unsigned long i = 0; i < size2; i++) {
+ if (!hwcap2_flags[i].valid)
+ ODP_PRINT("%s ", hwcap2_flags[i].feat_flag);
+ }
+
+ ODP_PRINT("\n\n");
+}
+
+void _odp_cpu_flags_print_all(void)
+{
+ _odp_sys_info_print_acle_flags();
+ _odp_sys_info_print_hwcap_flags();
+}