Index: sys/arm64/arm64/identcpu.c =================================================================== --- sys/arm64/arm64/identcpu.c +++ sys/arm64/arm64/identcpu.c @@ -48,8 +48,6 @@ #include static void print_cpu_features(u_int cpu); -static u_long parse_cpu_features_hwcap(void); -static u_long parse_cpu_features_hwcap2(void); char machine[] = "arm64"; @@ -270,16 +268,32 @@ #define MRS_FIELD_VALUE_END { .desc = NULL } +struct mrs_field_hwcap { + u_long *hwcap; + uint64_t min; + u_long hwcap_val; +}; + +#define MRS_HWCAP(_hwcap, _val, _min) \ +{ \ + .hwcap = (_hwcap), \ + .hwcap_val = (_val), \ + .min = (_min), \ +} + +#define MRS_HWCAP_END { .hwcap = NULL } + struct mrs_field { const char *name; struct mrs_field_value *values; + struct mrs_field_hwcap *hwcaps; uint64_t mask; bool sign; u_int type; u_int shift; }; -#define MRS_FIELD(_register, _name, _sign, _type, _values) \ +#define MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, _hwcap) \ { \ .name = #_name, \ .sign = (_sign), \ @@ -287,8 +301,12 @@ .shift = _register ## _ ## _name ## _SHIFT, \ .mask = _register ## _ ## _name ## _MASK, \ .values = (_values), \ + .hwcaps = (_hwcap), \ } +#define MRS_FIELD(_register, _name, _sign, _type, _values) \ + MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, NULL) + #define MRS_FIELD_END { .type = MRS_INVALID, } /* ID_AA64AFR0_EL1 */ @@ -394,6 +412,11 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_rndr_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_RNG, ID_AA64ISAR0_RNDR_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_tlb[] = { MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_NONE, ""), MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_TLBIOS, "TLBI-OS"), @@ -408,78 +431,154 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_ts_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_FLAGM, ID_AA64ISAR0_TS_CondM_8_4), + MRS_HWCAP(&elf_hwcap2, HWCAP2_FLAGM2, ID_AA64ISAR0_TS_CondM_8_5), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_fhm[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, FHM, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_fhm_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDFHM, ID_AA64ISAR0_FHM_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_dp[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, DP, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_dp_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDDP, ID_AA64ISAR0_DP_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_sm4[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM4, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_sm4_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SM4, ID_AA64ISAR0_SM4_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_sm3[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM3, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_sm3_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SM3, ID_AA64ISAR0_SM3_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_sha3[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA3, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_sha3_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SHA3, ID_AA64ISAR0_SHA3_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_rdm[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, RDM, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_rdm_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDRDM, ID_AA64ISAR0_RDM_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_atomic[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, Atomic, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_atomic_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_ATOMICS, ID_AA64ISAR0_Atomic_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_crc32[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, CRC32, NONE, BASE), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_crc32_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_CRC32, ID_AA64ISAR0_CRC32_BASE), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_sha2[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA2, NONE, BASE), MRS_FIELD_VALUE(ID_AA64ISAR0_SHA2_512, "SHA2+SHA512"), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_sha2_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SHA2, ID_AA64ISAR0_SHA2_BASE), + MRS_HWCAP(&elf_hwcap, HWCAP_SHA512, ID_AA64ISAR0_SHA2_512), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_sha1[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA1, NONE, BASE), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_sha1_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SHA1, ID_AA64ISAR0_SHA1_BASE), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar0_aes[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, AES, NONE, BASE), MRS_FIELD_VALUE(ID_AA64ISAR0_AES_PMULL, "AES+PMULL"), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar0_aes_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_AES, ID_AA64ISAR0_AES_BASE), + MRS_HWCAP(&elf_hwcap, HWCAP_PMULL, ID_AA64ISAR0_AES_PMULL), + MRS_HWCAP_END +}; + static struct mrs_field id_aa64isar0_fields[] = { - MRS_FIELD(ID_AA64ISAR0, RNDR, false, MRS_LOWER, id_aa64isar0_rndr), + MRS_FIELD_HWCAP(ID_AA64ISAR0, RNDR, false, MRS_LOWER, + id_aa64isar0_rndr, id_aa64isar0_rndr_caps), MRS_FIELD(ID_AA64ISAR0, TLB, false, MRS_EXACT, id_aa64isar0_tlb), - MRS_FIELD(ID_AA64ISAR0, TS, false, MRS_LOWER, id_aa64isar0_ts), - MRS_FIELD(ID_AA64ISAR0, FHM, false, MRS_LOWER, id_aa64isar0_fhm), - MRS_FIELD(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp), - MRS_FIELD(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4), - MRS_FIELD(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3), - MRS_FIELD(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3), - MRS_FIELD(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm), - MRS_FIELD(ID_AA64ISAR0, Atomic, false, MRS_LOWER, id_aa64isar0_atomic), - MRS_FIELD(ID_AA64ISAR0, CRC32, false, MRS_LOWER, id_aa64isar0_crc32), - MRS_FIELD(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2), - MRS_FIELD(ID_AA64ISAR0, SHA1, false, MRS_LOWER, id_aa64isar0_sha1), - MRS_FIELD(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes), + MRS_FIELD_HWCAP(ID_AA64ISAR0, TS, false, MRS_LOWER, id_aa64isar0_ts, + id_aa64isar0_ts_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, FHM, false, MRS_LOWER, id_aa64isar0_fhm, + id_aa64isar0_fhm_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp, + id_aa64isar0_dp_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4, + id_aa64isar0_sm4_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3, + id_aa64isar0_sm3_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3, + id_aa64isar0_sha3_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm, + id_aa64isar0_rdm_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, Atomic, false, MRS_LOWER, + id_aa64isar0_atomic, id_aa64isar0_atomic_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, CRC32, false, MRS_LOWER, + id_aa64isar0_crc32, id_aa64isar0_crc32_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2, + id_aa64isar0_sha2_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA1, false, MRS_LOWER, + id_aa64isar0_sha1, id_aa64isar0_sha1_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes, + id_aa64isar0_aes_caps), MRS_FIELD_END, }; @@ -490,16 +589,31 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_i8mm_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_I8MM, ID_AA64ISAR1_I8MM_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_dgh[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, DGH, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_dgh_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_DGH, ID_AA64ISAR1_DGH_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_bf16[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, BF16, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_bf16_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_BF16, ID_AA64ISAR1_BF16_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_specres[] = { MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_NONE, ""), MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_IMPL, "PredInv"), @@ -511,11 +625,21 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_sb_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SB, ID_AA64ISAR1_SB_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_frintts[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FRINTTS, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_frintts_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_FRINT, ID_AA64ISAR1_FRINTTS_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_gpi[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPI, NONE, IMPL), MRS_FIELD_VALUE_END, @@ -533,16 +657,32 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_lrcpc_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_LRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_3), + MRS_HWCAP(&elf_hwcap, HWCAP_ILRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_4), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_fcma[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FCMA, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_fcma_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_FCMA, ID_AA64ISAR1_FCMA_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_jscvt[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, JSCVT, NONE, IMPL), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_jscvt_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_JSCVT, ID_AA64ISAR1_JSCVT_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64isar1_api[] = { MRS_FIELD_VALUE(ID_AA64ISAR1_API_NONE, ""), MRS_FIELD_VALUE(ID_AA64ISAR1_API_PAC, "API PAC"), @@ -564,23 +704,37 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64isar1_dpb_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_DCPOP, ID_AA64ISAR1_DPB_DCCVAP), + MRS_HWCAP(&elf_hwcap2, HWCAP2_DCPODP, ID_AA64ISAR1_DPB_DCCVADP), + MRS_HWCAP_END +}; + static struct mrs_field id_aa64isar1_fields[] = { - MRS_FIELD(ID_AA64ISAR1, I8MM, false, MRS_LOWER, id_aa64isar1_i8mm), - MRS_FIELD(ID_AA64ISAR1, DGH, false, MRS_LOWER, id_aa64isar1_dgh), - MRS_FIELD(ID_AA64ISAR1, BF16, false, MRS_LOWER, id_aa64isar1_bf16), + MRS_FIELD_HWCAP(ID_AA64ISAR1, I8MM, false, MRS_LOWER, + id_aa64isar1_i8mm, id_aa64isar1_i8mm_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR1, DGH, false, MRS_LOWER, id_aa64isar1_dgh, + id_aa64isar1_dgh_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR1, BF16, false, MRS_LOWER, + id_aa64isar1_bf16, id_aa64isar1_bf16_caps), MRS_FIELD(ID_AA64ISAR1, SPECRES, false, MRS_EXACT, id_aa64isar1_specres), - MRS_FIELD(ID_AA64ISAR1, SB, false, MRS_LOWER, id_aa64isar1_sb), - MRS_FIELD(ID_AA64ISAR1, FRINTTS, false, MRS_LOWER, - id_aa64isar1_frintts), + MRS_FIELD_HWCAP(ID_AA64ISAR1, SB, false, MRS_LOWER, id_aa64isar1_sb, + id_aa64isar1_sb_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR1, FRINTTS, false, MRS_LOWER, + id_aa64isar1_frintts, id_aa64isar1_frintts_caps), MRS_FIELD(ID_AA64ISAR1, GPI, false, MRS_EXACT, id_aa64isar1_gpi), MRS_FIELD(ID_AA64ISAR1, GPA, false, MRS_EXACT, id_aa64isar1_gpa), - MRS_FIELD(ID_AA64ISAR1, LRCPC, false, MRS_LOWER, id_aa64isar1_lrcpc), - MRS_FIELD(ID_AA64ISAR1, FCMA, false, MRS_LOWER, id_aa64isar1_fcma), - MRS_FIELD(ID_AA64ISAR1, JSCVT, false, MRS_LOWER, id_aa64isar1_jscvt), + MRS_FIELD_HWCAP(ID_AA64ISAR1, LRCPC, false, MRS_LOWER, + id_aa64isar1_lrcpc, id_aa64isar1_lrcpc_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR1, FCMA, false, MRS_LOWER, + id_aa64isar1_fcma, id_aa64isar1_fcma_caps), + MRS_FIELD_HWCAP(ID_AA64ISAR1, JSCVT, false, MRS_LOWER, + id_aa64isar1_jscvt, id_aa64isar1_jscvt_caps), MRS_FIELD(ID_AA64ISAR1, API, false, MRS_EXACT, id_aa64isar1_api), MRS_FIELD(ID_AA64ISAR1, APA, false, MRS_EXACT, id_aa64isar1_apa), - MRS_FIELD(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb), + MRS_FIELD_HWCAP(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb, + id_aa64isar1_dpb_caps), MRS_FIELD_END, }; @@ -786,6 +940,11 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64mmfr2_at_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_USCAT, ID_AA64MMFR2_AT_IMPL), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64mmfr2_st[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, ST, NONE, IMPL), MRS_FIELD_VALUE_END, @@ -836,7 +995,8 @@ MRS_FIELD(ID_AA64MMFR2, TTL, false, MRS_EXACT, id_aa64mmfr2_ttl), MRS_FIELD(ID_AA64MMFR2, FWB, false, MRS_EXACT, id_aa64mmfr2_fwb), MRS_FIELD(ID_AA64MMFR2, IDS, false, MRS_EXACT, id_aa64mmfr2_ids), - MRS_FIELD(ID_AA64MMFR2, AT, false, MRS_LOWER, id_aa64mmfr2_at), + MRS_FIELD_HWCAP(ID_AA64MMFR2, AT, false, MRS_LOWER, id_aa64mmfr2_at, + id_aa64mmfr2_at_caps), MRS_FIELD(ID_AA64MMFR2, ST, false, MRS_EXACT, id_aa64mmfr2_st), MRS_FIELD(ID_AA64MMFR2, NV, false, MRS_EXACT, id_aa64mmfr2_nv), MRS_FIELD(ID_AA64MMFR2, CCIDX, false, MRS_EXACT, id_aa64mmfr2_ccidx), @@ -870,6 +1030,11 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64pfr0_dit_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_DIT, ID_AA64PFR0_DIT_PSTATE), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64pfr0_amu[] = { MRS_FIELD_VALUE(ID_AA64PFR0_AMU_NONE, ""), MRS_FIELD_VALUE(ID_AA64PFR0_AMU_V1, "AMUv1"), @@ -891,6 +1056,14 @@ MRS_FIELD_VALUE_END, }; +#if 0 +/* Enable when we add SVE support */ +static struct mrs_field_hwcap id_aa64pfr0_sve_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL), + MRS_HWCAP_END +}; +#endif + static struct mrs_field_value id_aa64pfr0_ras[] = { MRS_FIELD_VALUE(ID_AA64PFR0_RAS_NONE, ""), MRS_FIELD_VALUE(ID_AA64PFR0_RAS_IMPL, "RAS"), @@ -909,12 +1082,24 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64pfr0_advsimd_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_ASIMD, ID_AA64PFR0_AdvSIMD_IMPL), + MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDHP, ID_AA64PFR0_AdvSIMD_HP), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64pfr0_fp[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, FP, NONE, IMPL), MRS_FIELD_VALUE(ID_AA64PFR0_FP_HP, "FP+HP"), MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64pfr0_fp_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_FP, ID_AA64PFR0_FP_IMPL), + MRS_HWCAP(&elf_hwcap, HWCAP_FPHP, ID_AA64PFR0_FP_HP), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64pfr0_el3[] = { MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL3, NONE, 64), MRS_FIELD_VALUE(ID_AA64PFR0_EL3_64_32, "EL3 32"), @@ -942,15 +1127,18 @@ static struct mrs_field id_aa64pfr0_fields[] = { MRS_FIELD(ID_AA64PFR0, CSV3, false, MRS_EXACT, id_aa64pfr0_csv3), MRS_FIELD(ID_AA64PFR0, CSV2, false, MRS_EXACT, id_aa64pfr0_csv2), - MRS_FIELD(ID_AA64PFR0, DIT, false, MRS_LOWER, id_aa64pfr0_dit), + MRS_FIELD_HWCAP(ID_AA64PFR0, DIT, false, MRS_LOWER, id_aa64pfr0_dit, + id_aa64pfr0_dit_caps), MRS_FIELD(ID_AA64PFR0, AMU, false, MRS_EXACT, id_aa64pfr0_amu), MRS_FIELD(ID_AA64PFR0, MPAM, false, MRS_EXACT, id_aa64pfr0_mpam), MRS_FIELD(ID_AA64PFR0, SEL2, false, MRS_EXACT, id_aa64pfr0_sel2), MRS_FIELD(ID_AA64PFR0, SVE, false, MRS_EXACT, id_aa64pfr0_sve), MRS_FIELD(ID_AA64PFR0, RAS, false, MRS_EXACT, id_aa64pfr0_ras), MRS_FIELD(ID_AA64PFR0, GIC, false, MRS_EXACT, id_aa64pfr0_gic), - MRS_FIELD(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER, id_aa64pfr0_advsimd), - MRS_FIELD(ID_AA64PFR0, FP, true, MRS_LOWER, id_aa64pfr0_fp), + MRS_FIELD_HWCAP(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER, + id_aa64pfr0_advsimd, id_aa64pfr0_advsimd_caps), + MRS_FIELD_HWCAP(ID_AA64PFR0, FP, true, MRS_LOWER, id_aa64pfr0_fp, + id_aa64pfr0_fp_caps), MRS_FIELD(ID_AA64PFR0, EL3, false, MRS_EXACT, id_aa64pfr0_el3), MRS_FIELD(ID_AA64PFR0, EL2, false, MRS_EXACT, id_aa64pfr0_el2), MRS_FIELD(ID_AA64PFR0, EL1, false, MRS_LOWER, id_aa64pfr0_el1), @@ -974,15 +1162,29 @@ MRS_FIELD_VALUE_END, }; +static struct mrs_field_hwcap id_aa64pfr1_ssbs_caps[] = { + MRS_HWCAP(&elf_hwcap, HWCAP_SSBS, ID_AA64PFR1_SSBS_PSTATE), + MRS_HWCAP_END +}; + static struct mrs_field_value id_aa64pfr1_bt[] = { MRS_FIELD_VALUE(ID_AA64PFR1_BT_NONE, ""), MRS_FIELD_VALUE(ID_AA64PFR1_BT_IMPL, "BTI"), MRS_FIELD_VALUE_END, }; +#if 0 +/* Enable when we add BTI support */ +static struct mrs_field_hwcap id_aa64pfr1_bt_caps[] = { + MRS_HWCAP(&elf_hwcap2, HWCAP2_BTI, ID_AA64PFR1_BT_IMPL), + MRS_HWCAP_END +}; +#endif + static struct mrs_field id_aa64pfr1_fields[] = { MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte), - MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs), + MRS_FIELD_HWCAP(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs, + id_aa64pfr1_ssbs_caps), MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt), MRS_FIELD_END, }; @@ -1264,6 +1466,41 @@ int64_t icache_line_size; /* The minimum I cache line size */ int64_t idcache_line_size; /* The minimum cache line size */ +/* + * Find the values to export to userspace as AT_HWCAP and AT_HWCAP2. + */ +static void +parse_cpu_features(void) +{ + struct mrs_field_hwcap *hwcaps; + struct mrs_field *fields; + uint64_t min, reg; + int i, j, k; + + for (i = 0; i < nitems(user_regs); i++) { + reg = CPU_DESC_FIELD(user_cpu_desc, i); + fields = user_regs[i].fields; + for (j = 0; fields[j].type != 0; j++) { + hwcaps = fields[j].hwcaps; + if (hwcaps == NULL) + continue; + + for (k = 0; hwcaps[k].hwcap != NULL; k++) { + min = hwcaps[k].min; + + /* + * If the field is greater than the minimum + * value we can set the hwcap; + */ + if (mrs_field_cmp(reg, min, fields[j].shift, + 4, fields[j].sign) >= 0) { + *hwcaps[k].hwcap |= hwcaps[k].hwcap_val; + } + } + } + } +} + static void identify_cpu_sysinit(void *dummy __unused) { @@ -1284,9 +1521,8 @@ idc = false; } - /* Exposed to userspace as AT_HWCAP and AT_HWCAP2 */ - elf_hwcap = parse_cpu_features_hwcap(); - elf_hwcap2 = parse_cpu_features_hwcap2(); + /* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2 */ + parse_cpu_features(); if (dic && idc) { arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range; @@ -1318,186 +1554,6 @@ } SYSINIT(cpu_features, SI_SUB_SMP, SI_ORDER_ANY, cpu_features_sysinit, NULL); -static u_long -parse_cpu_features_hwcap(void) -{ - u_long hwcap = 0; - - switch (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0)) { - case ID_AA64ISAR0_TS_CondM_8_4: - case ID_AA64ISAR0_TS_CondM_8_5: - hwcap |= HWCAP_FLAGM; - break; - default: - break; - } - - if (ID_AA64ISAR0_FHM_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_FHM_IMPL) - hwcap |= HWCAP_ASIMDFHM; - - if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_DP_IMPL) - hwcap |= HWCAP_ASIMDDP; - - if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_SM4_IMPL) - hwcap |= HWCAP_SM4; - - if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_SM3_IMPL) - hwcap |= HWCAP_SM3; - - if (ID_AA64ISAR0_SHA3_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_SHA3_IMPL) - hwcap |= HWCAP_SHA3; - - if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_RDM_IMPL) - hwcap |= HWCAP_ASIMDRDM; - - if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_Atomic_IMPL) - hwcap |= HWCAP_ATOMICS; - - if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_CRC32_BASE) - hwcap |= HWCAP_CRC32; - - switch (ID_AA64ISAR0_SHA2_VAL(user_cpu_desc.id_aa64isar0)) { - case ID_AA64ISAR0_SHA2_BASE: - hwcap |= HWCAP_SHA2; - break; - case ID_AA64ISAR0_SHA2_512: - hwcap |= HWCAP_SHA2 | HWCAP_SHA512; - break; - default: - break; - } - - if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_SHA1_BASE) - hwcap |= HWCAP_SHA1; - - switch (ID_AA64ISAR0_AES_VAL(user_cpu_desc.id_aa64isar0)) { - case ID_AA64ISAR0_AES_BASE: - hwcap |= HWCAP_AES; - break; - case ID_AA64ISAR0_AES_PMULL: - hwcap |= HWCAP_PMULL | HWCAP_AES; - break; - default: - break; - } - - if (ID_AA64ISAR1_SB_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_SB_IMPL) - hwcap |= HWCAP_SB; - - switch (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1)) { - case ID_AA64ISAR1_LRCPC_RCPC_8_3: - hwcap |= HWCAP_LRCPC; - break; - case ID_AA64ISAR1_LRCPC_RCPC_8_4: - hwcap |= HWCAP_LRCPC | HWCAP_ILRCPC; - break; - default: - break; - } - - if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_FCMA_IMPL) - hwcap |= HWCAP_FCMA; - - if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_JSCVT_IMPL) - hwcap |= HWCAP_JSCVT; - - if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_DPB_DCCVAP) - hwcap |= HWCAP_DCPOP; - - if (ID_AA64MMFR2_AT_VAL(user_cpu_desc.id_aa64mmfr2) == - ID_AA64MMFR2_AT_IMPL) - hwcap |= HWCAP_USCAT; - - if (ID_AA64PFR0_DIT_VAL(user_cpu_desc.id_aa64pfr0) == - ID_AA64PFR0_DIT_PSTATE) - hwcap |= HWCAP_DIT; - - if (ID_AA64PFR0_SVE_VAL(user_cpu_desc.id_aa64pfr0) == - ID_AA64PFR0_SVE_IMPL) - hwcap |= HWCAP_SVE; - - switch (ID_AA64PFR0_AdvSIMD_VAL(user_cpu_desc.id_aa64pfr0)) { - case ID_AA64PFR0_AdvSIMD_IMPL: - hwcap |= HWCAP_ASIMD; - break; - case ID_AA64PFR0_AdvSIMD_HP: - hwcap |= HWCAP_ASIMD | HWCAP_ASIMDHP; - break; - default: - break; - } - - switch (ID_AA64PFR0_FP_VAL(user_cpu_desc.id_aa64pfr0)) { - case ID_AA64PFR0_FP_IMPL: - hwcap |= HWCAP_FP; - break; - case ID_AA64PFR0_FP_HP: - hwcap |= HWCAP_FP | HWCAP_FPHP; - break; - default: - break; - } - - if (ID_AA64PFR1_SSBS_VAL(user_cpu_desc.id_aa64pfr1) == - ID_AA64PFR1_SSBS_PSTATE_MSR) - hwcap |= HWCAP_SSBS; - - return (hwcap); -} - -static u_long -parse_cpu_features_hwcap2(void) -{ - u_long hwcap2 = 0; - - if (ID_AA64ISAR0_RNDR_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_RNDR_IMPL) - hwcap2 |= HWCAP2_RNG; - - if (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0) == - ID_AA64ISAR0_TS_CondM_8_5) - hwcap2 |= HWCAP2_FLAGM2; - - if (ID_AA64ISAR1_I8MM_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_I8MM_IMPL) - hwcap2 |= HWCAP2_I8MM; - - if (ID_AA64ISAR1_DGH_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_DGH_IMPL) - hwcap2 |= HWCAP2_DGH; - - if (ID_AA64ISAR1_BF16_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_BF16_IMPL) - hwcap2 |= HWCAP2_BF16; - - if (ID_AA64ISAR1_FRINTTS_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_FRINTTS_IMPL) - hwcap2 |= HWCAP2_FRINT; - - if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_DPB_DCCVADP) - hwcap2 |= HWCAP2_DCPODP; - - if (ID_AA64PFR1_BT_VAL(user_cpu_desc.id_aa64pfr1) == - ID_AA64PFR1_BT_IMPL) - hwcap2 |= HWCAP2_BTI; - - return (hwcap2); -} - static void print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg) {