111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/*
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (C) 2010 The Android Open Source Project
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * All rights reserved.
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Redistribution and use in source and binary forms, with or without
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * modification, are permitted provided that the following conditions
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * are met:
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *  * Redistributions of source code must retain the above copyright
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    notice, this list of conditions and the following disclaimer.
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *  * Redistributions in binary form must reproduce the above copyright
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    notice, this list of conditions and the following disclaimer in
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    the documentation and/or other materials provided with the
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    distribution.
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * SUCH DAMAGE.
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* ChangeLog for this library:
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r10e?: Add MIPS MSA feature.
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r10: Support for 64-bit CPUs (Intel, ARM & MIPS).
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r8d: Add android_setCpu().
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *          VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt.
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *          Rewrite the code to parse /proc/self/auxv instead of
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *          the "Features" field in /proc/cpuinfo.
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *          Dynamically allocate the buffer that hold the content
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *          of /proc/cpuinfo to deal with newer hardware.
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r7c: Fix CPU count computation. The old method only reported the
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *           number of _active_ CPUs when the library was initialized,
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *           which could be less than the real total.
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         for an ARMv6 CPU (see below).
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         Handle kernels that only report 'neon', and not 'vfpv3'
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         (VFPv3 is mandated by the ARM architecture is Neon is implemented)
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         Handle kernels that only report 'vfpv3d16', and not 'vfpv3'
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *         android_getCpuFamily().
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NDK r4: Initial release
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "cpu-features.h"
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <dlfcn.h>
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <errno.h>
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <fcntl.h>
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <pthread.h>
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h>
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdlib.h>
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <sys/system_properties.h>
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <unistd.h>
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  pthread_once_t     g_once;
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  int                g_inited;
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  AndroidCpuFamily   g_cpuFamily;
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  uint64_t           g_cpuFeatures;
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  int                g_cpuCount;
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic  uint32_t           g_cpuIdArm;
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const int android_cpufeatures_debug = 0;
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define  D(...) \
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    do { \
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (android_cpufeatures_debug) { \
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            printf(__VA_ARGS__); fflush(stdout); \
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } \
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } while (0)
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __i386__
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ void x86_cpuid(int func, int values[4])
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int a, b, c, d;
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* We need to preserve ebx since we're compiling PIC code */
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* this means we can't use "=b" for the second output register */
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __asm__ __volatile__ ( \
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "push %%ebx\n"
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "cpuid\n" \
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "mov %%ebx, %1\n"
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "pop %%ebx\n"
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      : "a" (func) \
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    );
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[0] = a;
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[1] = b;
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[2] = c;
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[3] = d;
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__x86_64__)
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ void x86_cpuid(int func, int values[4])
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int64_t a, b, c, d;
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* We need to preserve ebx since we're compiling PIC code */
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* this means we can't use "=b" for the second output register */
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __asm__ __volatile__ ( \
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "push %%rbx\n"
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "cpuid\n" \
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "mov %%rbx, %1\n"
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      "pop %%rbx\n"
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      : "a" (func) \
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    );
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[0] = a;
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[1] = b;
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[2] = c;
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    values[3] = d;
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Get the size of a file by reading it until the end. This is needed
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * because files under /proc do not always return a valid size when
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertget_file_size(const char* pathname)
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert   int fd, result = 0;
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char buffer[256];
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    fd = open(pathname, O_RDONLY);
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fd < 0) {
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Can't open %s: %s\n", pathname, strerror(errno));
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return -1;
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (;;) {
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        int ret = read(fd, buffer, sizeof buffer);
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret < 0) {
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (errno == EINTR)
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue;
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Error while reading %s: %s\n", pathname, strerror(errno));
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret == 0)
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result += ret;
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    close(fd);
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Read the content of /proc/cpuinfo into a user-provided buffer.
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Return the length of the data, or -1 on error. Does *not*
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * zero-terminate the content. Will not read more
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * than 'buffsize' bytes.
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertread_file(const char*  pathname, char*  buffer, size_t  buffsize)
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int  fd, count;
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    fd = open(pathname, O_RDONLY);
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fd < 0) {
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Could not open %s: %s\n", pathname, strerror(errno));
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return -1;
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    count = 0;
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (count < (int)buffsize) {
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        int ret = read(fd, buffer + count, buffsize - count);
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret < 0) {
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (errno == EINTR)
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue;
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Error while reading from %s: %s\n", pathname, strerror(errno));
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (count == 0)
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                count = -1;
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret == 0)
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        count += ret;
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    close(fd);
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return count;
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Extract the content of a the first occurence of a given field in
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * the content of /proc/cpuinfo and return it as a heap-allocated
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * string that must be freed by the caller.
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Return NULL if not found
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic char*
21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertextract_cpuinfo_field(const char* buffer, int buflen, const char* field)
21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int  fieldlen = strlen(field);
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char* bufend = buffer + buflen;
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char* result = NULL;
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int len;
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char *p, *q;
21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Look for first field occurence, and ensures it starts the line. */
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    p = buffer;
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (;;) {
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p = memmem(p, bufend-p, field, fieldlen);
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (p == NULL)
22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            goto EXIT;
22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (p == buffer || p[-1] == '\n')
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p += fieldlen;
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Skip to the first column followed by a space */
23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    p += fieldlen;
23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    p  = memchr(p, ':', bufend-p);
23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (p == NULL || p[1] != ' ')
23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        goto EXIT;
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Find the end of the line */
23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    p += 2;
23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    q = memchr(p, '\n', bufend-p);
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (q == NULL)
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        q = bufend;
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Copy the line into a heap-allocated buffer */
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    len = q-p;
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    result = malloc(len+1);
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (result == NULL)
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        goto EXIT;
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    memcpy(result, p, len);
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    result[len] = '\0';
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
25211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertEXIT:
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Checks that a space-separated list of items contains one given 'item'.
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Returns 1 if found, 0 otherwise.
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberthas_list_item(const char* list, const char* item)
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char*  p = list;
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int itemlen = strlen(item);
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (list == NULL)
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return 0;
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (*p) {
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char*  q;
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* skip spaces */
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        while (*p == ' ' || *p == '\t')
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            p++;
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* find end of current list item */
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        q = p;
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        while (*q && *q != ' ' && *q != '\t')
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            q++;
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (itemlen == q-p && !memcmp(p, item, itemlen))
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return 1;
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* skip to next item */
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p = q;
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return 0;
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif /* __arm__ */
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Parse a number starting from 'input', but not going further
29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * than 'limit'. Return the value into '*result'.
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NOTE: Does not skip over leading spaces, or deal with sign characters.
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NOTE: Ignores overflows.
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * The function returns NULL in case of error (bad format), or the new
29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * position after the decimal number in case of success (which will always
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * be <= 'limit').
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char*
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertparse_number(const char* input, const char* limit, int base, int* result)
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char* p = input;
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int val = 0;
30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (p < limit) {
30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        int d = (*p - '0');
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((unsigned)d >= 10U) {
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            d = (*p - 'a');
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if ((unsigned)d >= 6U)
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              d = (*p - 'A');
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if ((unsigned)d >= 6U)
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              break;
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            d += 10;
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (d >= base)
31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          break;
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        val = val*base + d;
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p++;
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (p == input)
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return NULL;
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    *result = val;
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return p;
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char*
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertparse_decimal(const char* input, const char* limit, int* result)
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return parse_number(input, limit, 10, result);
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char*
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertparse_hexadecimal(const char* input, const char* limit, int* result)
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return parse_number(input, limit, 16, result);
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif /* __arm__ */
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* This small data type is used to represent a CPU list / mask, as read
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * For now, we don't expect more than 32 cores on mobile devices, so keep
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * everything simple.
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypedef struct {
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t mask;
34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} CpuList;
35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ void
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_init(CpuList* list) {
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    list->mask = 0;
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ void
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_and(CpuList* list1, CpuList* list2) {
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    list1->mask &= list2->mask;
35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ void
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_set(CpuList* list, int index) {
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((unsigned)index < 32) {
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        list->mask |= (uint32_t)(1U << index);
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic __inline__ int
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_count(CpuList* list) {
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return __builtin_popcount(list->mask);
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Parse a textual list of cpus and store the result inside a CpuList object.
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Input format is the following:
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * - comma-separated list of items (no spaces)
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * - each item is either a single decimal number (cpu index), or a range made
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   of two numbers separated by a single dash (-). Ranges are inclusive.
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Examples:   0
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *             2,4-127,128-143
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *             0-1
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_parse(CpuList* list, const char* line, int line_len)
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char* p = line;
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char* end = p + line_len;
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char* q;
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* NOTE: the input line coming from sysfs typically contains a
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert     * trailing newline, so take care of it in the code below
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert     */
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (p < end && *p != '\n')
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        int val, start_value, end_value;
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Find the end of current item, and put it into 'q' */
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        q = memchr(p, ',', end-p);
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (q == NULL) {
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            q = end;
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Get first value */
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p = parse_decimal(p, q, &start_value);
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (p == NULL)
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            goto BAD_FORMAT;
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        end_value = start_value;
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* If we're not at the end of the item, expect a dash and
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * and integer; extract end value.
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         */
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (p < q && *p == '-') {
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            p = parse_decimal(p+1, q, &end_value);
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (p == NULL)
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                goto BAD_FORMAT;
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Set bits CPU list bits */
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (val = start_value; val <= end_value; val++) {
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            cpulist_set(list, val);
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Jump to next item */
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        p = q;
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (p < end)
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            p++;
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
43011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertBAD_FORMAT:
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ;
43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Read a CPU list from one sysfs file */
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertcpulist_read_from(CpuList* list, const char* filename)
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char   file[64];
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int    filelen;
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpulist_init(list);
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    filelen = read_file(filename, file, sizeof file);
44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (filelen < 0) {
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Could not read %s: %s\n", filename, strerror(errno));
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return;
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpulist_parse(list, file, filelen);
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__aarch64__)
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// see <uapi/asm/hwcap.h> kernel header
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_FP                (1 << 0)
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_ASIMD             (1 << 1)
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_AES               (1 << 3)
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_PMULL             (1 << 4)
45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_SHA1              (1 << 5)
45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_SHA2              (1 << 6)
45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_CRC32             (1 << 7)
46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__arm__)
46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// See <asm/hwcap.h> kernel header.
46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_VFP       (1 << 6)
46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_IWMMXT    (1 << 9)
46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_NEON      (1 << 12)
46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_VFPv3     (1 << 13)
46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_VFPv3D16  (1 << 14)
47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_VFPv4     (1 << 16)
47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_IDIVA     (1 << 17)
47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_IDIVT     (1 << 18)
47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// see <uapi/asm/hwcap.h> kernel header
47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP2_AES     (1 << 0)
47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP2_PMULL   (1 << 1)
47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP2_SHA1    (1 << 2)
47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP2_SHA2    (1 << 3)
47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP2_CRC32   (1 << 4)
48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This is the list of 32-bit ARMv7 optional features that are _always_
48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference
48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Manual.
48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_SET_FOR_ARMV8  \
48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  ( HWCAP_VFP | \
48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    HWCAP_NEON | \
48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    HWCAP_VFPv3 | \
48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    HWCAP_VFPv4 | \
48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    HWCAP_IDIVA | \
49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    HWCAP_IDIVT )
49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__mips__)
49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// see <uapi/asm/hwcap.h> kernel header
49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_MIPS_R6           (1 << 0)
49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define HWCAP_MIPS_MSA          (1 << 1)
49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define AT_HWCAP 16
50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define AT_HWCAP2 26
50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Probe the system's C library for a 'getauxval' function and call it if
50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// it exits, or return 0 for failure. This function is available since API
50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// level 20.
50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the
50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// edge case where some NDK developers use headers for a platform that is
51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// newer than the one really targetted by their application.
51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This is typically done to use newer native APIs only when running on more
51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// recent Android versions, and requires careful symbol management.
51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Note that getauxval() can't really be re-implemented here, because
51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// its implementation does not parse /proc/self/auxv. Instead it depends
51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// on values  that are passed by the kernel at process-init time to the
51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// C runtime initialization layer.
51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t
51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertget_elf_hwcap_from_getauxval(int hwcap_type) {
52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef unsigned long getauxval_func_t(unsigned long);
52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dlerror();
52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    void* libc_handle = dlopen("libc.so", RTLD_NOW);
52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!libc_handle) {
52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Could not dlopen() C library: %s\n", dlerror());
52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return 0;
52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t ret = 0;
53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    getauxval_func_t* func = (getauxval_func_t*)
53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            dlsym(libc_handle, "getauxval");
53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!func) {
53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Could not find getauxval() in C library\n");
53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Note: getauxval() returns 0 on failure. Doesn't touch errno.
53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ret = (uint32_t)(*func)(hwcap_type);
53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dlclose(libc_handle);
53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return ret;
54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__arm__)
54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the
54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// current CPU. Note that this file is not accessible from regular
54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// application processes on some Android platform releases.
54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// On success, return new ELF hwcaps, or 0 on failure.
54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t
54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertget_elf_hwcap_from_proc_self_auxv(void) {
55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const char filepath[] = "/proc/self/auxv";
55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY));
55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fd < 0) {
55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Could not open %s: %s\n", filepath, strerror(errno));
55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return 0;
55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    struct { uint32_t tag; uint32_t value; } entry;
55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t result = 0;
56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (;;) {
56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry));
56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret < 0) {
56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Error while reading %s: %s\n", filepath, strerror(errno));
56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            break;
56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Detect end of list.
56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (ret == 0 || (entry.tag == 0 && entry.value == 0))
56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          break;
56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (entry.tag == AT_HWCAP) {
57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          result = entry.value;
57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          break;
57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    close(fd);
57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Compute the ELF HWCAP flags from the content of /proc/cpuinfo.
57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * This works by parsing the 'Features' line, which lists which optional
58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * features the device's CPU supports, on top of its reference
58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * architecture.
58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic uint32_t
58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertget_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) {
58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t hwcaps = 0;
58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    long architecture = 0;
58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (cpuArch) {
58911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        architecture = strtol(cpuArch, NULL, 10);
59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        free(cpuArch);
59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (architecture >= 8L) {
59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel.
59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // The 'Features' line only lists the optional features that the
59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // device's CPU supports, compared to its reference architecture
59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // which are of no use for this process.
59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture);
59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return HWCAP_SET_FOR_ARMV8;
59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (cpuFeatures != NULL) {
60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Found cpuFeatures = '%s'\n", cpuFeatures);
60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "vfp"))
60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_VFP;
60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "vfpv3"))
60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_VFPv3;
61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "vfpv3d16"))
61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_VFPv3D16;
61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "vfpv4"))
61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_VFPv4;
61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "neon"))
61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_NEON;
61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "idiva"))
61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_IDIVA;
61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "idivt"))
61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_IDIVT;
62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "idiv"))
62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (has_list_item(cpuFeatures, "iwmmxt"))
62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps |= HWCAP_IWMMXT;
62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        free(cpuFeatures);
62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return hwcaps;
62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif  /* __arm__ */
63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Return the number of cpus present on a given device.
63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * To handle all weird kernel configurations, we need to compute the
63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * intersection of the 'present' and 'possible' CPU lists and count
63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * the result.
63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int
63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertget_cpu_count(void)
63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    CpuList cpus_present[1];
64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    CpuList cpus_possible[1];
64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present");
64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible");
64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Compute the intersection of both sets to get the actual number of
64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert     * CPU cores that can be used on this device by the kernel.
64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert     */
64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpulist_and(cpus_present, cpus_possible);
65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return cpulist_count(cpus_present);
65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void
65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_cpuInitFamily(void)
65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__arm__)
65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__i386__)
66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_X86;
66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__mips64)
66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Needs to be before __mips__ since the compiler defines both */
66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64;
66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__mips__)
66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__aarch64__)
66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_ARM64;
66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif defined(__x86_64__)
66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_X86_64;
67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else
67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void
67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_cpuInit(void)
67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char* cpuinfo = NULL;
67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int   cpuinfo_len;
68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    android_cpuInitFamily();
68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFeatures = 0;
68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuCount    = 1;
68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_inited      = 1;
68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpuinfo_len = get_file_size("/proc/cpuinfo");
68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (cpuinfo_len < 0) {
68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      D("cpuinfo_len cannot be computed!");
69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return;
69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpuinfo = malloc(cpuinfo_len);
69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (cpuinfo == NULL) {
69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      D("cpuinfo buffer could not be allocated");
69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return;
69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len);
69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (cpuinfo_len < 0)  /* should not happen */ {
70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        free(cpuinfo);
70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return;
70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Count the CPU cores, the value may be 0 for single-core CPUs */
70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuCount = get_cpu_count();
70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (g_cpuCount == 0) {
70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuCount = 1;
71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    D("found cpuCount = %d\n", g_cpuCount);
71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract architecture from the "CPU Architecture" field.
71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * The list is well-known, unlike the the output of
71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * the 'Processor' field which can vary greatly.
71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         *
72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * See the definition of the 'proc_arch' array in
72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         * same file.
72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert         */
72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (cpuArch != NULL) {
72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char*  end;
72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            long   archNumber;
72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int    hasARMv7 = 0;
73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("found cpuArch = '%s'\n", cpuArch);
73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            /* read the initial decimal number, ignore the rest */
73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            archNumber = strtol(cpuArch, &end, 10);
73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            /* Note that ARMv8 is upwards compatible with ARMv7. */
73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (end > cpuArch && archNumber >= 7) {
73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                hasARMv7 = 1;
73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            /* Unfortunately, it seems that certain ARMv6-based CPUs
74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * report an incorrect architecture number of 7!
74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             *
74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * See http://code.google.com/p/android/issues/detail?id=10812
74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             *
74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * We try to correct this by looking at the 'elf_format'
74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * field reported by the 'Processor' field, which is of the
74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * an ARMv6-one.
75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             */
75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (hasARMv7) {
75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                      "Processor");
75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (cpuProc != NULL) {
75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    D("found cpuProc = '%s'\n", cpuProc);
75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if (has_list_item(cpuProc, "(v6l)")) {
75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        D("CPU processor and architecture mismatch!!\n");
75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        hasARMv7 = 0;
75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    }
76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    free(cpuProc);
76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (hasARMv7) {
76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            /* The LDREX / STREX instructions are available from ARMv6 */
76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (archNumber >= 6) {
77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            free(cpuArch);
77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract the list of CPU features from ELF hwcaps */
77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t hwcaps = 0;
77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!hwcaps) {
78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps = get_elf_hwcap_from_proc_self_auxv();
78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!hwcaps) {
78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Parsing /proc/self/auxv will fail from regular application
78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // processes on some Android platform versions, when this happens
78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // parse proc/cpuinfo instead.
78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n");
78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len);
78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (hwcaps != 0) {
79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_vfp = (hwcaps & HWCAP_VFP);
79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_vfpv3 = (hwcaps & HWCAP_VFPv3);
79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16);
79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_vfpv4 = (hwcaps & HWCAP_VFPv4);
79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_neon = (hwcaps & HWCAP_NEON);
79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_idiva = (hwcaps & HWCAP_IDIVA);
79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_idivt = (hwcaps & HWCAP_IDIVT);
79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_iwmmxt = (hwcaps & HWCAP_IWMMXT);
80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // The kernel does a poor job at ensuring consistency when
80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // describing CPU features. So lots of guessing is needed.
80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // 'vfpv4' implies VFPv3|VFP_FMA|FP16
80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_vfpv4)
80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3    |
80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 ANDROID_CPU_ARM_FEATURE_VFP_FMA;
80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
81011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
81111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // a value of 'vfpv3' doesn't necessarily mean that the D32
81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // feature is present, so be conservative. All CPUs in the
81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // field that support D32 also support NEON, so this should
81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // not be a problem in practice.
81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_vfpv3 || has_vfpv3d16)
81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // 'vfp' is super ambiguous. Depending on the kernel, it can
81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_vfp) {
82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              else
82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_neon) {
82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 ANDROID_CPU_ARM_FEATURE_NEON |
83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 ANDROID_CPU_ARM_FEATURE_VFP_D32;
83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (has_vfpv4)
83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // VFPv3 implies VFPv2 and ARMv7
83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 ANDROID_CPU_ARM_FEATURE_ARMv7;
84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_idiva)
84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_idivt)
84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_iwmmxt)
84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract the list of CPU features from ELF hwcaps2 */
85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t hwcaps2 = 0;
85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2);
85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (hwcaps2 != 0) {
85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_aes     = (hwcaps2 & HWCAP2_AES);
85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_pmull   = (hwcaps2 & HWCAP2_PMULL);
85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_sha1    = (hwcaps2 & HWCAP2_SHA1);
85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_sha2    = (hwcaps2 & HWCAP2_SHA2);
85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_crc32   = (hwcaps2 & HWCAP2_CRC32);
85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_aes)
86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_pmull)
86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_sha1)
86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_sha2)
86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
86811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_crc32)
86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract the cpuid value from various fields */
87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // The CPUID value is broken up in several entries in /proc/cpuinfo.
87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // This table is used to rebuild it from the entries.
87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        static const struct CpuIdEntry {
87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const char* field;
87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char        format;
87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char        bit_lshift;
87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char        bit_length;
87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } cpu_id_entries[] = {
88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { "CPU implementer", 'x', 24, 8 },
88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { "CPU variant", 'x', 20, 4 },
88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { "CPU part", 'x', 4, 12 },
88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { "CPU revision", 'd', 0, 4 },
88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        };
88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        size_t i;
88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        D("Parsing /proc/cpuinfo to recover CPUID\n");
88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (i = 0;
88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             ++i) {
89011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const struct CpuIdEntry* entry = &cpu_id_entries[i];
89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char* value = extract_cpuinfo_field(cpuinfo,
89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                cpuinfo_len,
89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                entry->field);
89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (value == NULL)
89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                continue;
89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            D("field=%s value='%s'\n", entry->field, value);
89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char* value_end = value + strlen(value);
89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int val = 0;
90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const char* start = value;
90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const char* p;
90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              start += 2;
90411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              p = parse_hexadecimal(start, value_end, &val);
90511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else if (entry->format == 'x')
90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              p = parse_hexadecimal(value, value_end, &val);
90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else
90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              p = parse_decimal(value, value_end, &val);
90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (p > (const char*)start) {
91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              val &= ((1 << entry->bit_length)-1);
91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              val <<= entry->bit_lshift;
91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              g_cpuIdArm |= (uint32_t) val;
91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            free(value);
91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Handle kernel configuration bugs that prevent the correct
92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // reporting of CPU features.
92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        static const struct CpuFix {
92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            uint32_t  cpuid;
92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            uint64_t  or_flags;
92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } cpu_fixes[] = {
92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            /* The Nexus 4 (Qualcomm Krait) kernel configuration
92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             * forgets to report IDIV support. */
92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        };
93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        size_t n;
93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) {
93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const struct CpuFix* entry = &cpu_fixes[n];
93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (g_cpuIdArm == entry->cpuid)
93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= entry->or_flags;
93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Special case: The emulator-specific Android 4.2 kernel fails
94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // to report support for the 32-bit ARM IDIV instruction.
94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Technically, this is a feature of the virtual CPU implemented
94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // by the emulator. Note that it could also support Thumb IDIV
94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // in the future, and this will have to be slightly updated.
94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        char* hardware = extract_cpuinfo_field(cpuinfo,
94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                               cpuinfo_len,
94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                               "Hardware");
94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (hardware) {
94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (!strcmp(hardware, "Goldfish") &&
95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuIdArm == 0x4100c080 &&
95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) {
95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            free(hardware);
95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif /* __arm__ */
95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __aarch64__
95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract the list of CPU features from ELF hwcaps */
96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t hwcaps = 0;
96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (hwcaps != 0) {
96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_fp      = (hwcaps & HWCAP_FP);
96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_asimd   = (hwcaps & HWCAP_ASIMD);
96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_aes     = (hwcaps & HWCAP_AES);
96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_pmull   = (hwcaps & HWCAP_PMULL);
96811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_sha1    = (hwcaps & HWCAP_SHA1);
96911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_sha2    = (hwcaps & HWCAP_SHA2);
97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_crc32   = (hwcaps & HWCAP_CRC32);
97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if(has_fp == 0) {
97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                D("ERROR: Floating-point unit missing, but is required by Android on AArch64 CPUs\n");
97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if(has_asimd == 0) {
97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                D("ERROR: ASIMD unit missing, but is required by Android on AArch64 CPUs\n");
97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_fp)
98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
98111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_asimd)
98211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
98311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_aes)
98411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
98511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_pmull)
98611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
98711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_sha1)
98811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
98911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_sha2)
99011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
99111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_crc32)
99211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
99311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
99411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
99511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif /* __aarch64__ */
99611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
99711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__i386__) || defined(__x86_64__)
99811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int regs[4];
99911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
100011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* According to http://en.wikipedia.org/wiki/CPUID */
100111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define VENDOR_INTEL_b  0x756e6547
100211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define VENDOR_INTEL_c  0x6c65746e
100311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define VENDOR_INTEL_d  0x49656e69
100411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
100511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    x86_cpuid(0, regs);
100611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
100711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         regs[2] == VENDOR_INTEL_c &&
100811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         regs[3] == VENDOR_INTEL_d);
100911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
101011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    x86_cpuid(1, regs);
101111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 9)) != 0) {
101211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
101311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
101411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 23)) != 0) {
101511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
101611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
101711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 19)) != 0) {
101811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1;
101911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
102011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 20)) != 0) {
102111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2;
102211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
102311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
102411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
102511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
102611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 25)) != 0) {
102711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI;
102811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
102911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 28)) != 0) {
103011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX;
103111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
103211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[2] & (1 << 30)) != 0) {
103311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND;
103411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
103511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
103611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    x86_cpuid(7, regs);
103711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[1] & (1 << 5)) != 0) {
103811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2;
103911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
104011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((regs[1] & (1 << 29)) != 0) {
104111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI;
104211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
104311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
104411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
104511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
104611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined( __mips__)
104711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {   /* MIPS and MIPS64 */
104811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        /* Extract the list of CPU features from ELF hwcaps */
104911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t hwcaps = 0;
105011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
105111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (hwcaps != 0) {
105211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_r6      = (hwcaps & HWCAP_MIPS_R6);
105311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            int has_msa     = (hwcaps & HWCAP_MIPS_MSA);
105411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_r6)
105511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6;
105611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (has_msa)
105711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA;
105811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
105911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
106011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif /* __mips__ */
106111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
106211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    free(cpuinfo);
106311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
106411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
106511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
106611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertAndroidCpuFamily
106711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_getCpuFamily(void)
106811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
106911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pthread_once(&g_once, android_cpuInit);
107011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return g_cpuFamily;
107111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
107211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
107311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
107411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertuint64_t
107511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_getCpuFeatures(void)
107611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
107711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pthread_once(&g_once, android_cpuInit);
107811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return g_cpuFeatures;
107911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
108011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
108111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
108211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint
108311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_getCpuCount(void)
108411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
108511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pthread_once(&g_once, android_cpuInit);
108611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return g_cpuCount;
108711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
108811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
108911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void
109011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_cpuInitDummy(void)
109111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
109211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_inited = 1;
109311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
109411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
109511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint
109611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_setCpu(int cpu_count, uint64_t cpu_features)
109711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
109811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* Fail if the library was already initialized. */
109911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (g_inited)
110011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return 0;
110111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
110211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    android_cpuInitFamily();
110311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
110411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuFeatures = cpu_features;
110511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pthread_once(&g_once, android_cpuInitDummy);
110611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
110711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return 1;
110811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
110911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
111011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
111111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertuint32_t
111211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_getCpuIdArm(void)
111311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
111411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pthread_once(&g_once, android_cpuInit);
111511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return g_cpuIdArm;
111611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
111711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
111811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint
111911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertandroid_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
112011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
112111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!android_setCpu(cpu_count, cpu_features))
112211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return 0;
112311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
112411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    g_cpuIdArm = cpu_id;
112511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return 1;
112611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
112711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif  /* __arm__ */
112811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
112911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/*
113011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Technical note: Making sense of ARM's FPU architecture versions.
113111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
113211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPA was ARM's first attempt at an FPU architecture. There is no Android
113311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * device that actually uses it since this technology was already obsolete
113411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * when the project started. If you see references to FPA instructions
113511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * somewhere, you can be sure that this doesn't apply to Android at all.
113611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
113711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of
113811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * new versions / additions to it. ARM considers this obsolete right now,
113911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * and no known Android device implements it either.
114011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
114111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv2 added a few instructions to VFPv1, and is an *optional* extension
114211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * supported by some ARMv5TE, ARMv6 and ARMv6T2 CPUs. Note that a device
114311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * supporting the 'armeabi' ABI doesn't necessarily support these.
114411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
114511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv3-D16 adds a few instructions on top of VFPv2 and is typically used
114611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * on ARMv7-A CPUs which implement a FPU. Note that it is also mandated
114711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * by the Android 'armeabi-v7a' ABI. The -D16 suffix in its name means
114811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * that it provides 16 double-precision FPU registers (d0-d15) and 32
114911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * single-precision ones (s0-s31) which happen to be mapped to the same
115011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * register banks.
115111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
115211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv3-D32 is the name of an extension to VFPv3-D16 that provides 16
115311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * additional double precision registers (d16-d31). Note that there are
115411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * still only 32 single precision registers.
115511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
115611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv3xD is a *subset* of VFPv3-D16 that only provides single-precision
115711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * registers. It is only used on ARMv7-M (i.e. on micro-controllers) which
115811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * are not supported by Android. Note that it is not compatible with VFPv2.
115911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
116011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NOTE: The term 'VFPv3' usually designate either VFPv3-D16 or VFPv3-D32
116111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *       depending on context. For example GCC uses it for VFPv3-D32, but
116211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *       the Linux kernel code uses it for VFPv3-D16 (especially in
116311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *       /proc/cpuinfo). Always try to use the full designation when
116411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *       possible.
116511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
116611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NEON, a.k.a. "ARM Advanced SIMD" is an extension that provides
116711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * instructions to perform parallel computations on vectors of 8, 16,
116811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 32, 64 and 128 bit quantities. NEON requires VFPv32-D32 since all
116911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NEON registers are also mapped to the same register banks.
117011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
117111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv4-D16, adds a few instructions on top of VFPv3-D16 in order to
117211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * perform fused multiply-accumulate on VFP registers, as well as
117311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * half-precision (16-bit) conversion operations.
117411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
117511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFPv4-D32 is VFPv4-D16 with 32, instead of 16, FPU double precision
117611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * registers.
117711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
117811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VPFv4-NEON is VFPv4-D32 with NEON instructions. It also adds fused
117911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * multiply-accumulate instructions that work on the NEON registers.
118011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
118111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * NOTE: Similarly, "VFPv4" might either reference VFPv4-D16 or VFPv4-D32
118211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *       depending on context.
118311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
118411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * The following information was determined by scanning the binutils-2.22
118511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * sources:
118611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
118711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Basic VFP instruction subsets:
118811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
118911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_V1xD 0x08000000     // Base VFP instruction set.
119011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_V1   0x04000000     // Double-precision insns.
119111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_V2   0x02000000     // ARM10E VFPr1.
119211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_V3xD 0x01000000     // VFPv3 single-precision.
119311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_V3   0x00800000     // VFPv3 double-precision.
119411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_NEON_EXT_V1  0x00400000     // Neon (SIMD) insns.
119511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_D32  0x00200000     // Registers D16-D31.
119611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_FP16 0x00100000     // Half-precision extensions.
119711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_NEON_EXT_FMA 0x00080000     // Neon fused multiply-add
119811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * #define FPU_VFP_EXT_FMA  0x00040000     // VFP fused multiply-add
119911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
120011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU types (excluding NEON)
120111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
120211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_V1xD (EXT_V1xD)
120311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |
120411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    +--------------------------+
120511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                          |
120611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_V1 (+EXT_V1)       FPU_VFP_V3xD (+EXT_V2+EXT_V3xD)
120711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                          |
120811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                          |
120911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_V2 (+EXT_V2)       FPU_VFP_V4_SP_D16 (+EXT_FP16+EXT_FMA)
121011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |
121111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_V3D16 (+EXT_Vx3D+EXT_V3)
121211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |
121311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    +--------------------------+
121411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                          |
121511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_V3 (+EXT_D32)     FPU_VFP_V4D16 (+EXT_FP16+EXT_FMA)
121611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                          |
121711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |                      FPU_VFP_V4 (+EXT_D32)
121811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    |
121911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * FPU_VFP_HARD (+EXT_FMA+NEON_EXT_FMA)
122011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
122111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * VFP architectures:
122211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
122311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V1xD  (EXT_V1xD)
122411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
122511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +------------------+
122611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                  |
122711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |             ARCH_VFP_V3xD (+EXT_V2+EXT_V3xD)
122811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                  |
122911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |             ARCH_VFP_V3xD_FP16 (+EXT_FP16)
123011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                  |
123111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |             ARCH_VFP_V4_SP_D16 (+EXT_FMA)
123211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
123311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V1 (+EXT_V1)
123411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
123511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V2 (+EXT_V2)
123611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
123711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3D16 (+EXT_V3xD+EXT_V3)
123811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
123911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
124011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
124111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V3D16_FP16  (+EXT_FP16)
124211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
124311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
124411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
124511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
124611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
124711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V4 (+EXT_D32)
124811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
124911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
125011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
125111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3 (+EXT_D32)
125211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
125311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
125411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
125511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V3_FP16 (+EXT_FP16)
125611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
125711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
125811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
125911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_NEON_FP16 (+EXT_FP16)
126011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
126111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * -fpu=<name> values and their correspondance with FPU architectures above:
126211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
126311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfp",               FPU_ARCH_VFP_V2},
126411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfp9",              FPU_ARCH_VFP_V2},
126511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfp3",              FPU_ARCH_VFP_V3}, // For backwards compatbility.
126611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfp10",             FPU_ARCH_VFP_V2},
126711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfp10-r0",          FPU_ARCH_VFP_V1},
126811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpxd",             FPU_ARCH_VFP_V1xD},
126911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv2",             FPU_ARCH_VFP_V2},
127011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3",             FPU_ARCH_VFP_V3},
127111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3-fp16",        FPU_ARCH_VFP_V3_FP16},
127211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3-d16",         FPU_ARCH_VFP_V3D16},
127311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3-d16-fp16",    FPU_ARCH_VFP_V3D16_FP16},
127411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3xd",           FPU_ARCH_VFP_V3xD},
127511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv3xd-fp16",      FPU_ARCH_VFP_V3xD_FP16},
127611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"neon",              FPU_ARCH_VFP_V3_PLUS_NEON_V1},
127711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"neon-fp16",         FPU_ARCH_NEON_FP16},
127811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv4",             FPU_ARCH_VFP_V4},
127911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"vfpv4-d16",         FPU_ARCH_VFP_V4D16},
128011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"fpv4-sp-d16",       FPU_ARCH_VFP_V4_SP_D16},
128111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   {"neon-vfpv4",        FPU_ARCH_NEON_VFP_V4},
128211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
128311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
128411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Simplified diagram that only includes FPUs supported by Android:
128511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Only ARCH_VFP_V3D16 is actually mandated by the armeabi-v7a ABI,
128611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * all others are optional and must be probed at runtime.
128711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
128811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3D16 (EXT_V1xD+EXT_V1+EXT_V2+EXT_V3xD+EXT_V3)
128911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
129011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
129111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
129211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V3D16_FP16  (+EXT_FP16)
129311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
129411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
129511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
129611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
129711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
129811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V4 (+EXT_D32)
129911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
130011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
130111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
130211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3 (+EXT_D32)
130311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
130411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   +-------------------+
130511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |                   |
130611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |         ARCH_VFP_V3_FP16 (+EXT_FP16)
130711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
130811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
130911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *   |
131011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * ARCH_NEON_FP16 (+EXT_FP16)
131111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
131211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
1313