62 #if defined(__le32__) || defined(__le64__)
67 #else // !__le32__ && !__le64__
77 #include <sys/system_properties.h>
93 if (android_cpufeatures_debug) { \
94 printf(__VA_ARGS__); fflush(stdout); \
99 static __inline__
void x86_cpuid(
int func,
int values[4])
104 __asm__ __volatile__ ( \
109 :
"=a" (a),
"=r" (b),
"=c" (c),
"=d" (d) \
126 int fd, ret, result = 0;
129 fd = open(pathname, O_RDONLY);
131 D(
"Can't open %s: %s\n", pathname, strerror(errno));
136 int ret =
read(fd, buffer,
sizeof buffer);
140 D(
"Error while reading %s: %s\n", pathname, strerror(errno));
158 read_file(
const char* pathname,
char* buffer,
size_t buffsize)
162 fd = open(pathname, O_RDONLY);
164 D(
"Could not open %s: %s\n", pathname, strerror(errno));
168 while (count < (
int)buffsize) {
169 int ret =
read(fd, buffer + count, buffsize - count);
173 D(
"Error while reading from %s: %s\n", pathname, strerror(errno));
195 int fieldlen = strlen(field);
196 const char* bufend = buffer + buflen;
204 p = (
const char *) memmem(p, bufend-p, field, fieldlen);
208 if (p == buffer || p[-1] ==
'\n')
216 p = (
const char *) memchr(p,
':', bufend-p);
217 if (p == NULL || p[1] !=
' ')
222 q = (
const char *) memchr(p,
'\n', bufend-p);
228 result = (
char *) malloc(len+1);
232 memcpy(result, p, len);
245 const char* p = list;
246 int itemlen = strlen(item);
255 while (*p ==
' ' || *p ==
'\t')
260 while (*q && *q !=
' ' && *q !=
'\t')
263 if (itemlen == q-p && !memcmp(p, item, itemlen))
283 parse_number(
const char* input,
const char* limit,
int base,
int* result)
285 const char* p = input;
289 if ((
unsigned)d >= 10U) {
291 if ((
unsigned)d >= 6U)
293 if ((
unsigned)d >= 6U)
331 static __inline__
void
336 static __inline__
void
341 static __inline__
void
343 if ((
unsigned)index < 32) {
344 list->
mask |= (uint32_t)(1U << index);
348 static __inline__
int
350 return __builtin_popcount(list->
mask);
366 const char* p = line;
367 const char* end = p + line_len;
373 while (p < end && *p !=
'\n')
375 int val, start_value, end_value;
378 q = (
const char *) memchr(p,
',', end-p);
388 end_value = start_value;
393 if (p < q && *p ==
'-') {
400 for (val = start_value; val <= end_value; val++) {
423 filelen =
read_file(filename, file,
sizeof file);
425 D(
"Could not read %s: %s\n", filename, strerror(errno));
435 #define HWCAP_VFP (1 << 6)
436 #define HWCAP_IWMMXT (1 << 9)
437 #define HWCAP_NEON (1 << 12)
438 #define HWCAP_VFPv3 (1 << 13)
439 #define HWCAP_VFPv3D16 (1 << 14)
440 #define HWCAP_VFPv4 (1 << 16)
441 #define HWCAP_IDIVA (1 << 17)
442 #define HWCAP_IDIVT (1 << 18)
447 #define HWCAP_SET_FOR_ARMV8 \
473 typedef unsigned long getauxval_func_t(
unsigned long);
476 void* libc_handle = dlopen(
"libc.so", RTLD_NOW);
478 D(
"Could not dlopen() C library: %s\n", dlerror());
483 getauxval_func_t* func = (getauxval_func_t*)
484 dlsym(libc_handle,
"getauxval");
486 D(
"Could not find getauxval() in C library\n");
489 ret = (uint32_t)(*func)(AT_HWCAP);
491 dlclose(libc_handle);
501 const char filepath[] =
"/proc/self/auxv";
502 int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY));
504 D(
"Could not open %s: %s\n", filepath, strerror(errno));
508 struct { uint32_t tag; uint32_t value; } entry;
512 int ret = TEMP_FAILURE_RETRY(
read(fd, (
char*)&entry,
sizeof entry));
514 D(
"Error while reading %s: %s\n", filepath, strerror(errno));
518 if (ret == 0 || (entry.tag == 0 && entry.value == 0))
520 if (entry.tag == AT_HWCAP) {
521 result = entry.value;
537 long architecture = 0;
540 architecture = strtol(cpuArch, NULL, 10);
543 if (architecture >= 8L) {
548 D(
"Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture);
549 return HWCAP_SET_FOR_ARMV8;
554 if (cpuFeatures != NULL) {
555 D(
"Found cpuFeatures = '%s'\n", cpuFeatures);
560 hwcaps |= HWCAP_VFPv3;
562 hwcaps |= HWCAP_VFPv3D16;
564 hwcaps |= HWCAP_VFPv4;
566 hwcaps |= HWCAP_NEON;
568 hwcaps |= HWCAP_IDIVA;
570 hwcaps |= HWCAP_IDIVT;
572 hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
574 hwcaps |= HWCAP_IWMMXT;
610 #elif defined(__i386__)
612 #elif defined(__mips64)
615 #elif defined(__mips__)
617 #elif defined(__aarch64__)
619 #elif defined(__x86_64__)
629 char* cpuinfo = NULL;
639 if (cpuinfo_len < 0) {
640 D(
"cpuinfo_len cannot be computed!");
643 cpuinfo = (
char *) malloc(cpuinfo_len);
644 if (cpuinfo == NULL) {
645 D(
"cpuinfo buffer could not be allocated");
648 cpuinfo_len =
read_file(
"/proc/cpuinfo", cpuinfo, cpuinfo_len);
649 D(
"cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
650 cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
652 if (cpuinfo_len < 0) {
677 if (cpuArch != NULL) {
682 D(
"found cpuArch = '%s'\n", cpuArch);
685 archNumber = strtol(cpuArch, &end, 10);
688 if (end > cpuArch && archNumber >= 7) {
705 if (cpuProc != NULL) {
706 D(
"found cpuProc = '%s'\n", cpuProc);
708 D(
"CPU processor and architecture mismatch!!\n");
720 if (archNumber >= 6) {
731 D(
"Parsing /proc/self/auxv to extract ELF hwcaps!\n");
738 D(
"Parsing /proc/cpuinfo to extract ELF hwcaps!\n");
743 int has_vfp = (hwcaps & HWCAP_VFP);
744 int has_vfpv3 = (hwcaps & HWCAP_VFPv3);
745 int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16);
746 int has_vfpv4 = (hwcaps & HWCAP_VFPv4);
747 int has_neon = (hwcaps & HWCAP_NEON);
748 int has_idiva = (hwcaps & HWCAP_IDIVA);
749 int has_idivt = (hwcaps & HWCAP_IDIVT);
750 int has_iwmmxt = (hwcaps & HWCAP_IWMMXT);
766 if (has_vfpv3 || has_vfpv3d16)
804 static const struct CpuIdEntry {
809 } cpu_id_entries[] = {
810 {
"CPU implementer",
'x', 24, 8 },
811 {
"CPU variant",
'x', 20, 4 },
812 {
"CPU part",
'x', 4, 12 },
813 {
"CPU revision",
'd', 0, 4 },
816 D(
"Parsing /proc/cpuinfo to recover CPUID\n");
818 i <
sizeof(cpu_id_entries)/
sizeof(cpu_id_entries[0]);
820 const struct CpuIdEntry* entry = &cpu_id_entries[i];
827 D(
"field=%s value='%s'\n", entry->field, value);
828 char* value_end = value + strlen(value);
830 const char* start = value;
832 if (value[0] ==
'0' && (value[1] ==
'x' || value[1] ==
'X')) {
835 }
else if (entry->format ==
'x')
840 if (p > (
const char*)start) {
841 val &= ((1 << entry->bit_length)-1);
842 val <<= entry->bit_lshift;
851 static const struct CpuFix {
863 for (n = 0; n <
sizeof(cpu_fixes)/
sizeof(cpu_fixes[0]); ++n) {
864 const struct CpuFix* entry = &cpu_fixes[n];
879 if (!strcmp(hardware,
"Goldfish") &&
893 #define VENDOR_INTEL_b 0x756e6547
894 #define VENDOR_INTEL_c 0x6c65746e
895 #define VENDOR_INTEL_d 0x49656e69
898 int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
899 regs[2] == VENDOR_INTEL_c &&
900 regs[3] == VENDOR_INTEL_d);
903 if ((regs[2] & (1 << 9)) != 0) {
906 if ((regs[2] & (1 << 23)) != 0) {
909 if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
955 g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
1166 #endif // defined(__le32__) || defined(__le64__)
void read(const service_ptr_t< file > &p_file, abort_callback &p_abort, pfc::string_base &p_out, bool &is_utf8)
static pthread_once_t g_once
static char * extract_cpuinfo_field(const char *buffer, int buflen, const char *field)
static uint64_t g_cpuFeatures
static AndroidCpuFamily g_cpuFamily
static uint32_t get_elf_hwcap_from_getauxval(void)
static void cpulist_parse(CpuList *list, const char *line, int line_len)
AndroidCpuFamily android_getCpuFamily(void)
static int get_file_size(const char *pathname)
uint64_t android_getCpuFeatures(void)
static uint32_t get_elf_hwcap_from_proc_self_auxv(void)
static uint32_t get_elf_hwcap_from_proc_cpuinfo(const char *cpuinfo, int cpuinfo_len)
static void android_cpuInitFamily(void)
static __inline__ void x86_cpuid(int func, int values[4])
int android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
static const char * parse_hexadecimal(const char *input, const char *limit, int *result)
int android_setCpu(int cpu_count, uint64_t cpu_features)
static __inline__ void cpulist_set(CpuList *list, int index)
static __inline__ void cpulist_init(CpuList *list)
static __inline__ int cpulist_count(CpuList *list)
static int read_file(const char *pathname, char *buffer, size_t buffsize)
static const char * parse_number(const char *input, const char *limit, int base, int *result)
static int has_list_item(const char *list, const char *item)
static const int android_cpufeatures_debug
static const char * parse_decimal(const char *input, const char *limit, int *result)
static void android_cpuInit(void)
static __inline__ void cpulist_and(CpuList *list1, CpuList *list2)
static void android_cpuInitDummy(void)
int android_getCpuCount(void)
static void cpulist_read_from(CpuList *list, const char *filename)
uint32_t android_getCpuIdArm(void)
static int get_cpu_count(void)
static uint32_t g_cpuIdArm