1 #include <stdint.h> 2 3 #include <arm/linux/api.h> 4 #include <cpuinfo/log.h> 5 6 cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(uint32_t features,uint32_t features2,uint32_t midr,const struct cpuinfo_arm_chipset chipset[restrict static1],struct cpuinfo_arm_isa isa[restrict static1])7void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo( 8 uint32_t features, 9 uint32_t features2, 10 uint32_t midr, 11 const struct cpuinfo_arm_chipset chipset[restrict static 1], 12 struct cpuinfo_arm_isa isa[restrict static 1]) 13 { 14 if (features & CPUINFO_ARM_LINUX_FEATURE_AES) { 15 isa->aes = true; 16 } 17 if (features & CPUINFO_ARM_LINUX_FEATURE_PMULL) { 18 isa->pmull = true; 19 } 20 if (features & CPUINFO_ARM_LINUX_FEATURE_SHA1) { 21 isa->sha1 = true; 22 } 23 if (features & CPUINFO_ARM_LINUX_FEATURE_SHA2) { 24 isa->sha2 = true; 25 } 26 if (features & CPUINFO_ARM_LINUX_FEATURE_CRC32) { 27 isa->crc32 = true; 28 } 29 if (features & CPUINFO_ARM_LINUX_FEATURE_ATOMICS) { 30 isa->atomics = true; 31 } 32 33 /* 34 * Some phones ship with an old kernel configuration that doesn't report NEON FP16 compute extension and SQRDMLAH/SQRDMLSH/UQRDMLAH/UQRDMLSH instructions. 35 * Use a MIDR-based heuristic to whitelist processors known to support it: 36 * - Processors with Cortex-A55 cores 37 * - Processors with Cortex-A65 cores 38 * - Processors with Cortex-A75 cores 39 * - Processors with Cortex-A76 cores 40 * - Processors with Cortex-A77 cores 41 * - Processors with Exynos M4 cores 42 * - Processors with Exynos M5 cores 43 * - Neoverse N1 cores 44 */ 45 if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) { 46 /* Exynos 9810 reports that it supports FP16 compute, but in fact only little cores do */ 47 cpuinfo_log_warning("FP16 arithmetics and RDM disabled: only little cores in Exynos 9810 support these extensions"); 48 } else { 49 const uint32_t fp16arith_mask = CPUINFO_ARM_LINUX_FEATURE_FPHP | CPUINFO_ARM_LINUX_FEATURE_ASIMDHP; 50 switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) { 51 case UINT32_C(0x4100D050): /* Cortex-A55 */ 52 case UINT32_C(0x4100D060): /* Cortex-A65 */ 53 case UINT32_C(0x4100D0B0): /* Cortex-A76 */ 54 case UINT32_C(0x4100D0C0): /* Neoverse N1 */ 55 case UINT32_C(0x4100D0D0): /* Cortex-A77 */ 56 case UINT32_C(0x4100D0E0): /* Cortex-A76AE */ 57 case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */ 58 case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */ 59 case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */ 60 case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */ 61 case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */ 62 case UINT32_C(0x53000030): /* Exynos M4 */ 63 case UINT32_C(0x53000040): /* Exynos M5 */ 64 isa->fp16arith = true; 65 isa->rdm = true; 66 break; 67 default: 68 if ((features & fp16arith_mask) == fp16arith_mask) { 69 isa->fp16arith = true; 70 } else if (features & CPUINFO_ARM_LINUX_FEATURE_FPHP) { 71 cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations"); 72 } else if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDHP) { 73 cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations"); 74 } 75 if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) { 76 isa->rdm = true; 77 } 78 break; 79 } 80 } 81 82 /* 83 * Many phones ship with an old kernel configuration that doesn't report UDOT/SDOT instructions. 84 * Use a MIDR-based heuristic to whitelist processors known to support it. 85 */ 86 switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) { 87 case UINT32_C(0x4100D060): /* Cortex-A65 */ 88 case UINT32_C(0x4100D0B0): /* Cortex-A76 */ 89 case UINT32_C(0x4100D0C0): /* Neoverse N1 */ 90 case UINT32_C(0x4100D0D0): /* Cortex-A77 */ 91 case UINT32_C(0x4100D0E0): /* Cortex-A76AE */ 92 case UINT32_C(0x4100D4A0): /* Neoverse E1 */ 93 case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */ 94 case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */ 95 case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */ 96 case UINT32_C(0x53000030): /* Exynos-M4 */ 97 case UINT32_C(0x53000040): /* Exynos-M5 */ 98 isa->dot = true; 99 break; 100 case UINT32_C(0x4100D050): /* Cortex A55: revision 1 or later only */ 101 isa->dot = !!(midr_get_variant(midr) >= 1); 102 break; 103 case UINT32_C(0x4100D0A0): /* Cortex A75: revision 2 or later only */ 104 isa->dot = !!(midr_get_variant(midr) >= 2); 105 break; 106 default: 107 if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDDP) { 108 isa->dot = true; 109 } 110 break; 111 } 112 if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) { 113 isa->jscvt = true; 114 } 115 if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) { 116 isa->jscvt = true; 117 } 118 if (features & CPUINFO_ARM_LINUX_FEATURE_FCMA) { 119 isa->fcma = true; 120 } 121 if (features & CPUINFO_ARM_LINUX_FEATURE_SVE) { 122 isa->sve = true; 123 } 124 if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SVE2) { 125 isa->sve2 = true; 126 } 127 } 128