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