static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) { if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) { /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always * available on ARMv8. Linux omits required features, so reading the * "Features" line does not work. (For simplicity, use strict equality. We * assume everything running on future ARM architectures will have a * working |getauxval|.) */ return HWCAP_NEON; } STRING_PIECE features; if (extract_cpuinfo_field(&features, cpuinfo, "Features") && has_list_item(&features, "neon")) { return HWCAP_NEON; } return 0; }
static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) { STRING_PIECE features; if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) { return 0; } unsigned long ret = 0; if (has_list_item(&features, "aes")) { ret |= HWCAP2_AES; } if (has_list_item(&features, "pmull")) { ret |= HWCAP2_PMULL; } if (has_list_item(&features, "sha1")) { ret |= HWCAP2_SHA1; } if (has_list_item(&features, "sha2")) { ret |= HWCAP2_SHA2; } return ret; }
static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field, const char *value) { STRING_PIECE extracted; return extract_cpuinfo_field(&extracted, cpuinfo, field) && STRING_PIECE_equals(&extracted, value); }
static void android_cpuInit(void) { char cpuinfo[4096]; int cpuinfo_len; g_cpuFamily = DEFAULT_CPU_FAMILY; g_cpuFeatures = 0; g_cpuCount = 1; cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo); D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len, cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo); if (cpuinfo_len < 0) /* should not happen */ { return; } /* Count the CPU cores, the value may be 0 for single-core CPUs */ g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor"); if (g_cpuCount == 0) { g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor"); if (g_cpuCount == 0) { g_cpuCount = 1; } } D("found cpuCount = %d\n", g_cpuCount); #ifdef __arm__ { char* features = NULL; char* architecture = NULL; /* Extract architecture from the "CPU Architecture" field. * The list is well-known, unlike the the output of * the 'Processor' field which can vary greatly. * * See the definition of the 'proc_arch' array in * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in * same file. */ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); if (cpuArch != NULL) { char* end; long archNumber; int hasARMv7 = 0; int hasARMv6 = 0; D("found cpuArch = '%s'\n", cpuArch); /* read the initial decimal number, ignore the rest */ archNumber = strtol(cpuArch, &end, 10); D("found archNumber = '%d'\n", archNumber); /* Here we assume that ARMv8 will be upwards compatible with v7 * in the future. Unfortunately, there is no 'Features' field to * indicate that Thumb-2 is supported. */ if (end > cpuArch ){ if (archNumber >= 7) { hasARMv7 = 1; } else if (archNumber == 6) { g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv6; } else { g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv5TE; } } else{ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv5TE; } /* Unfortunately, it seems that certain ARMv6-based CPUs * report an incorrect architecture number of 7! * * See http://code.google.com/p/android/issues/detail?id=10812 * * We try to correct this by looking at the 'elf_format' * field reported by the 'Processor' field, which is of the * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for * an ARMv6-one. */ if (hasARMv7) { char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor"); if (cpuProc != NULL) { D("found cpuProc = '%s'\n", cpuProc); if (has_list_item(cpuProc, "(v6l)")) { D("CPU processor and architecture mismatch!!\n"); hasARMv7 = 0; g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv6; } free(cpuProc); } } if (hasARMv7) { g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; } /* The LDREX / STREX instructions are available from ARMv6 */ if (archNumber >= 6) { g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; } free(cpuArch); } /* Extract the list of CPU features from 'Features' field */ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); if (cpuFeatures != NULL) { D("found cpuFeatures = '%s'\n", cpuFeatures); if (has_list_item(cpuFeatures, "vfpv3")) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; else if (has_list_item(cpuFeatures, "vfpv3d16")) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; if (has_list_item(cpuFeatures, "neon")) { /* Note: Certain kernels only report neon but not vfpv3 * in their features list. However, ARM mandates * that if Neon is implemented, so must be VFPv3 * so always set the flag. */ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON | ANDROID_CPU_ARM_FEATURE_VFPv3; } if (has_list_item(cpuFeatures, "vfp")){ g_cpuFeatures |=ANDROID_CPU_ARM_FEATURE_VFP; } free(cpuFeatures); } } #endif /* __arm__ */ #ifdef __i386__ g_cpuFamily = ANDROID_CPU_FAMILY_X86; #endif }