11e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* 21e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 31e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * 41e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * Use of this source code is governed by a BSD-style license 51e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * that can be found in the LICENSE file in the root of the source 61e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * tree. An additional intellectual property rights grant can be found 71e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * in the file PATENTS. All contributing project authors may 81e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * be found in the AUTHORS file in the root of the source tree. 91e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <sys/system_properties.h> 121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef __arm__ 131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <machine/cpu-features.h> 141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <pthread.h> 161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include "cpu-features.h" 171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <stdio.h> 181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <stdlib.h> 19340b4b89397f8911f3a42485129f9813f9da2541Elliott Hughes#include <string.h> 20340b4b89397f8911f3a42485129f9813f9da2541Elliott Hughes#include <unistd.h> 211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <fcntl.h> 221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include <errno.h> 231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic pthread_once_t g_once; 251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic AndroidCpuFamily g_cpuFamily; 261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic uint64_t g_cpuFeatures; 271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int g_cpuCount; 281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic const int android_cpufeatures_debug = 0; 301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef __arm__ 321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM 331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#elif defined __i386__ 341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86 351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#else 361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN 371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#define D(...) \ 401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora do { \ 411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (android_cpufeatures_debug) { \ 421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora printf(__VA_ARGS__); fflush(stdout); \ 431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } \ 441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } while (0) 451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef __i386__ 471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic __inline__ void x86_cpuid(int func, int values[4]) 481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int a, b, c, d; 501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* We need to preserve ebx since we're compiling PIC code */ 511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* this means we can't use "=b" for the second output register */ 521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora __asm__ __volatile__ ( \ 531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora "push %%ebx\n" 541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora "cpuid\n" \ 551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora "mov %1, %%ebx\n" 561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora "pop %%ebx\n" 571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : "a" (func) \ 591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ); 601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora values[0] = a; 611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora values[1] = b; 621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora values[2] = c; 631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora values[3] = d; 641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* Read the content of /proc/cpuinfo into a user-provided buffer. 681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * Return the length of the data, or -1 on error. Does *not* 691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * zero-terminate the content. Will not read more 701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * than 'buffsize' bytes. 711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int 731e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraread_file(const char* pathname, char* buffer, size_t buffsize) 741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int fd, len; 761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora fd = open(pathname, O_RDONLY); 781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (fd < 0) 791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return -1; 801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora do { 821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora len = read(fd, buffer, buffsize); 831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } while (len < 0 && errno == EINTR); 841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora close(fd); 861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return len; 881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* Extract the content of a the first occurence of a given field in 911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * the content of /proc/cpuinfo and return it as a heap-allocated 921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * string that must be freed by the caller. 931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * 941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * Return NULL if not found 951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic char* 971e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraextract_cpuinfo_field(char* buffer, int buflen, const char* field) 981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int fieldlen = strlen(field); 1001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* bufend = buffer + buflen; 1011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* result = NULL; 1021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int len, ignore; 1031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char *p, *q; 1041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Look for first field occurence, and ensures it starts the line. 1061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 1071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = buffer; 1081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora bufend = buffer + buflen; 1091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (;;) { 1101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = memmem(p, bufend-p, field, fieldlen); 1111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (p == NULL) 1121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora goto EXIT; 1131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (p == buffer || p[-1] == '\n') 1151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora break; 1161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p += fieldlen; 1181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Skip to the first column followed by a space */ 1211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p += fieldlen; 1221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = memchr(p, ':', bufend-p); 1231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (p == NULL || p[1] != ' ') 1241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora goto EXIT; 1251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Find the end of the line */ 1271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p += 2; 1281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q = memchr(p, '\n', bufend-p); 1291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (q == NULL) 1301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q = bufend; 1311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Copy the line into a heap-allocated buffer */ 1331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora len = q-p; 1341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora result = malloc(len+1); 1351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (result == NULL) 1361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora goto EXIT; 1371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora memcpy(result, p, len); 1391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora result[len] = '\0'; 1401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1411e7bf8805bd030c19924a5306837ecd72c295751Vikas AroraEXIT: 1421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return result; 1431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 1441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* Count the number of occurences of a given field prefix in /proc/cpuinfo. 1461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 1471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int 1481e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroracount_cpuinfo_field(char* buffer, int buflen, const char* field) 1491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 1501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int fieldlen = strlen(field); 1511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* p = buffer; 1521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* bufend = buffer + buflen; 1531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* q; 1541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int count = 0; 1551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora for (;;) { 1571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* q; 1581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = memmem(p, bufend-p, field, fieldlen); 1601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (p == NULL) 1611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora break; 1621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Ensure that the field is at the start of a line */ 1641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (p > buffer && p[-1] != '\n') { 1651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p += fieldlen; 1661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora continue; 1671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* skip any whitespace */ 1711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q = p + fieldlen; 1721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora while (q < bufend && (*q == ' ' || *q == '\t')) 1731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q++; 1741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* we must have a colon now */ 1761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (q < bufend && *q == ':') { 1771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora count += 1; 1781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q ++; 1791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = q; 1811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return count; 1841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 1851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* Like strlen(), but for constant string literals */ 1871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#define STRLEN_CONST(x) ((sizeof(x)-1) 1881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* Checks that a space-separated list of items contains one given 'item'. 1911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * Returns 1 if found, 0 otherwise. 1921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 1931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int 1941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorahas_list_item(const char* list, const char* item) 1951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 1961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* p = list; 1971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int itemlen = strlen(item); 1981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (list == NULL) 2001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return 0; 2011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora while (*p) { 2031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const char* q; 2041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* skip spaces */ 2061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora while (*p == ' ' || *p == '\t') 2071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p++; 2081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* find end of current list item */ 2101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q = p; 2111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora while (*q && *q != ' ' && *q != '\t') 2121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora q++; 2131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (itemlen == q-p && !memcmp(p, item, itemlen)) 2151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return 1; 2161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* skip to next item */ 2181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora p = q; 2191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return 0; 2211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 2221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic void 2251e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraandroid_cpuInit(void) 2261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 2271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char cpuinfo[4096]; 2281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int cpuinfo_len; 2291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFamily = DEFAULT_CPU_FAMILY; 2311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures = 0; 2321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuCount = 1; 2331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo); 2351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len, 2361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo); 2371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (cpuinfo_len < 0) /* should not happen */ { 2391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return; 2401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Count the CPU cores, the value may be 0 for single-core CPUs */ 2431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor"); 2441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (g_cpuCount == 0) { 2451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor"); 2461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (g_cpuCount == 0) { 2471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuCount = 1; 2481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("found cpuCount = %d\n", g_cpuCount); 2521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef __ARM_ARCH__ 2541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora { 2551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* features = NULL; 2561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* architecture = NULL; 2571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Extract architecture from the "CPU Architecture" field. 2591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * The list is well-known, unlike the the output of 2601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * the 'Processor' field which can vary greatly. 2611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * 2621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * See the definition of the 'proc_arch' array in 2631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in 2641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * same file. 2651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 2661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); 2671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (cpuArch != NULL) { 2691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* end; 2701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora long archNumber; 2711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int hasARMv7 = 0; 2721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("found cpuArch = '%s'\n", cpuArch); 2741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* read the initial decimal number, ignore the rest */ 2761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora archNumber = strtol(cpuArch, &end, 10); 2771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Here we assume that ARMv8 will be upwards compatible with v7 2791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * in the future. Unfortunately, there is no 'Features' field to 2801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * indicate that Thumb-2 is supported. 2811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 2821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (end > cpuArch && archNumber >= 7) { 2831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora hasARMv7 = 1; 2841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 2851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Unfortunately, it seems that certain ARMv6-based CPUs 2871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * report an incorrect architecture number of 7! 2881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * 2891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * See http://code.google.com/p/android/issues/detail?id=10812 2901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * 2911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * We try to correct this by looking at the 'elf_format' 2921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * field reported by the 'Processor' field, which is of the 2931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for 2941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * an ARMv6-one. 2951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 2961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (hasARMv7) { 2971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len, 2981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora "Processor"); 2991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (cpuProc != NULL) { 3001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("found cpuProc = '%s'\n", cpuProc); 3011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (has_list_item(cpuProc, "(v6l)")) { 3021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("CPU processor and architecture mismatch!!\n"); 3031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora hasARMv7 = 0; 3041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora free(cpuProc); 3061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (hasARMv7) { 3101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; 3111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* The LDREX / STREX instructions are available from ARMv6 */ 3141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (archNumber >= 6) { 3151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; 3161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora free(cpuArch); 3191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Extract the list of CPU features from 'Features' field */ 3221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); 3231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (cpuFeatures != NULL) { 3251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora D("found cpuFeatures = '%s'\n", cpuFeatures); 3271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (has_list_item(cpuFeatures, "vfpv3")) 3291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 3301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora else if (has_list_item(cpuFeatures, "vfpv3d16")) 3321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 3331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (has_list_item(cpuFeatures, "neon")) { 3351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora /* Note: Certain kernels only report neon but not vfpv3 3361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * in their features list. However, ARM mandates 3371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * that if Neon is implemented, so must be VFPv3 3381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora * so always set the flag. 3391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora */ 3401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON | 3411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ANDROID_CPU_ARM_FEATURE_VFPv3; 3421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora free(cpuFeatures); 3441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif /* __ARM_ARCH__ */ 3471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef __i386__ 3491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFamily = ANDROID_CPU_FAMILY_X86; 3501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int regs[4]; 3521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora/* According to http://en.wikipedia.org/wiki/CPUID */ 3541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#define VENDOR_INTEL_b 0x756e6547 3551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#define VENDOR_INTEL_c 0x6c65746e 3561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#define VENDOR_INTEL_d 0x49656e69 3571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora x86_cpuid(0, regs); 3591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int vendorIsIntel = (regs[1] == VENDOR_INTEL_b && 3601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora regs[2] == VENDOR_INTEL_c && 3611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora regs[3] == VENDOR_INTEL_d); 3621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora x86_cpuid(1, regs); 3641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if ((regs[2] & (1 << 9)) != 0) { 3651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; 3661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if ((regs[2] & (1 << 23)) != 0) { 3681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; 3691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) { 3711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; 3721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 3741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 3751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3771e7bf8805bd030c19924a5306837ecd72c295751Vikas AroraAndroidCpuFamily 3781e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraandroid_getCpuFamily(void) 3791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 3801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora pthread_once(&g_once, android_cpuInit); 3811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return g_cpuFamily; 3821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 3831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorauint64_t 3861e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraandroid_getCpuFeatures(void) 3871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 3881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora pthread_once(&g_once, android_cpuInit); 3891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return g_cpuFeatures; 3901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 3911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3931e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraint 3941e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraandroid_getCpuCount(void) 3951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora{ 3961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora pthread_once(&g_once, android_cpuInit); 3971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return g_cpuCount; 3981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 399