1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* ChangeLog for this library: 30 * 31 * NDK r10e?: Add MIPS MSA feature. 32 * 33 * NDK r10: Support for 64-bit CPUs (Intel, ARM & MIPS). 34 * 35 * NDK r8d: Add android_setCpu(). 36 * 37 * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16, 38 * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt. 39 * 40 * Rewrite the code to parse /proc/self/auxv instead of 41 * the "Features" field in /proc/cpuinfo. 42 * 43 * Dynamically allocate the buffer that hold the content 44 * of /proc/cpuinfo to deal with newer hardware. 45 * 46 * NDK r7c: Fix CPU count computation. The old method only reported the 47 * number of _active_ CPUs when the library was initialized, 48 * which could be less than the real total. 49 * 50 * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7 51 * for an ARMv6 CPU (see below). 52 * 53 * Handle kernels that only report 'neon', and not 'vfpv3' 54 * (VFPv3 is mandated by the ARM architecture is Neon is implemented) 55 * 56 * Handle kernels that only report 'vfpv3d16', and not 'vfpv3' 57 * 58 * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in 59 * android_getCpuFamily(). 60 * 61 * NDK r4: Initial release 62 */ 63 64 #include "cpu-features.h" 65 66 #include <dlfcn.h> 67 #include <errno.h> 68 #include <fcntl.h> 69 #include <pthread.h> 70 #include <stdio.h> 71 #include <stdlib.h> 72 #include <sys/system_properties.h> 73 #include <unistd.h> 74 75 static pthread_once_t g_once; 76 static int g_inited; 77 static AndroidCpuFamily g_cpuFamily; 78 static uint64_t g_cpuFeatures; 79 static int g_cpuCount; 80 81 #ifdef __arm__ 82 static uint32_t g_cpuIdArm; 83 #endif 84 85 static const int android_cpufeatures_debug = 0; 86 87 #define D(...) \ 88 do { \ 89 if (android_cpufeatures_debug) { \ 90 printf(__VA_ARGS__); fflush(stdout); \ 91 } \ 92 } while (0) 93 94 #ifdef __i386__ 95 static __inline__ void x86_cpuid(int func, int values[4]) 96 { 97 int a, b, c, d; 98 /* We need to preserve ebx since we're compiling PIC code */ 99 /* this means we can't use "=b" for the second output register */ 100 __asm__ __volatile__ ( \ 101 "push %%ebx\n" 102 "cpuid\n" \ 103 "mov %%ebx, %1\n" 104 "pop %%ebx\n" 105 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 106 : "a" (func) \ 107 ); 108 values[0] = a; 109 values[1] = b; 110 values[2] = c; 111 values[3] = d; 112 } 113 #elif defined(__x86_64__) 114 static __inline__ void x86_cpuid(int func, int values[4]) 115 { 116 int64_t a, b, c, d; 117 /* We need to preserve ebx since we're compiling PIC code */ 118 /* this means we can't use "=b" for the second output register */ 119 __asm__ __volatile__ ( \ 120 "push %%rbx\n" 121 "cpuid\n" \ 122 "mov %%rbx, %1\n" 123 "pop %%rbx\n" 124 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 125 : "a" (func) \ 126 ); 127 values[0] = a; 128 values[1] = b; 129 values[2] = c; 130 values[3] = d; 131 } 132 #endif 133 134 /* Get the size of a file by reading it until the end. This is needed 135 * because files under /proc do not always return a valid size when 136 * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. 137 */ 138 static int 139 get_file_size(const char* pathname) 140 { 141 142 int fd, result = 0; 143 char buffer[256]; 144 145 fd = open(pathname, O_RDONLY); 146 if (fd < 0) { 147 D("Can't open %s: %s\n", pathname, strerror(errno)); 148 return -1; 149 } 150 151 for (;;) { 152 int ret = read(fd, buffer, sizeof buffer); 153 if (ret < 0) { 154 if (errno == EINTR) 155 continue; 156 D("Error while reading %s: %s\n", pathname, strerror(errno)); 157 break; 158 } 159 if (ret == 0) 160 break; 161 162 result += ret; 163 } 164 close(fd); 165 return result; 166 } 167 168 /* Read the content of /proc/cpuinfo into a user-provided buffer. 169 * Return the length of the data, or -1 on error. Does *not* 170 * zero-terminate the content. Will not read more 171 * than 'buffsize' bytes. 172 */ 173 static int 174 read_file(const char* pathname, char* buffer, size_t buffsize) 175 { 176 int fd, count; 177 178 fd = open(pathname, O_RDONLY); 179 if (fd < 0) { 180 D("Could not open %s: %s\n", pathname, strerror(errno)); 181 return -1; 182 } 183 count = 0; 184 while (count < (int)buffsize) { 185 int ret = read(fd, buffer + count, buffsize - count); 186 if (ret < 0) { 187 if (errno == EINTR) 188 continue; 189 D("Error while reading from %s: %s\n", pathname, strerror(errno)); 190 if (count == 0) 191 count = -1; 192 break; 193 } 194 if (ret == 0) 195 break; 196 count += ret; 197 } 198 close(fd); 199 return count; 200 } 201 202 #ifdef __arm__ 203 /* Extract the content of a the first occurence of a given field in 204 * the content of /proc/cpuinfo and return it as a heap-allocated 205 * string that must be freed by the caller. 206 * 207 * Return NULL if not found 208 */ 209 static char* 210 extract_cpuinfo_field(const char* buffer, int buflen, const char* field) 211 { 212 int fieldlen = strlen(field); 213 const char* bufend = buffer + buflen; 214 char* result = NULL; 215 int len; 216 const char *p, *q; 217 218 /* Look for first field occurence, and ensures it starts the line. */ 219 p = buffer; 220 for (;;) { 221 p = memmem(p, bufend-p, field, fieldlen); 222 if (p == NULL) 223 goto EXIT; 224 225 if (p == buffer || p[-1] == '\n') 226 break; 227 228 p += fieldlen; 229 } 230 231 /* Skip to the first column followed by a space */ 232 p += fieldlen; 233 p = memchr(p, ':', bufend-p); 234 if (p == NULL || p[1] != ' ') 235 goto EXIT; 236 237 /* Find the end of the line */ 238 p += 2; 239 q = memchr(p, '\n', bufend-p); 240 if (q == NULL) 241 q = bufend; 242 243 /* Copy the line into a heap-allocated buffer */ 244 len = q-p; 245 result = malloc(len+1); 246 if (result == NULL) 247 goto EXIT; 248 249 memcpy(result, p, len); 250 result[len] = '\0'; 251 252 EXIT: 253 return result; 254 } 255 256 /* Checks that a space-separated list of items contains one given 'item'. 257 * Returns 1 if found, 0 otherwise. 258 */ 259 static int 260 has_list_item(const char* list, const char* item) 261 { 262 const char* p = list; 263 int itemlen = strlen(item); 264 265 if (list == NULL) 266 return 0; 267 268 while (*p) { 269 const char* q; 270 271 /* skip spaces */ 272 while (*p == ' ' || *p == '\t') 273 p++; 274 275 /* find end of current list item */ 276 q = p; 277 while (*q && *q != ' ' && *q != '\t') 278 q++; 279 280 if (itemlen == q-p && !memcmp(p, item, itemlen)) 281 return 1; 282 283 /* skip to next item */ 284 p = q; 285 } 286 return 0; 287 } 288 #endif /* __arm__ */ 289 290 /* Parse a number starting from 'input', but not going further 291 * than 'limit'. Return the value into '*result'. 292 * 293 * NOTE: Does not skip over leading spaces, or deal with sign characters. 294 * NOTE: Ignores overflows. 295 * 296 * The function returns NULL in case of error (bad format), or the new 297 * position after the decimal number in case of success (which will always 298 * be <= 'limit'). 299 */ 300 static const char* 301 parse_number(const char* input, const char* limit, int base, int* result) 302 { 303 const char* p = input; 304 int val = 0; 305 while (p < limit) { 306 int d = (*p - '0'); 307 if ((unsigned)d >= 10U) { 308 d = (*p - 'a'); 309 if ((unsigned)d >= 6U) 310 d = (*p - 'A'); 311 if ((unsigned)d >= 6U) 312 break; 313 d += 10; 314 } 315 if (d >= base) 316 break; 317 val = val*base + d; 318 p++; 319 } 320 if (p == input) 321 return NULL; 322 323 *result = val; 324 return p; 325 } 326 327 static const char* 328 parse_decimal(const char* input, const char* limit, int* result) 329 { 330 return parse_number(input, limit, 10, result); 331 } 332 333 #ifdef __arm__ 334 static const char* 335 parse_hexadecimal(const char* input, const char* limit, int* result) 336 { 337 return parse_number(input, limit, 16, result); 338 } 339 #endif /* __arm__ */ 340 341 /* This small data type is used to represent a CPU list / mask, as read 342 * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt 343 * 344 * For now, we don't expect more than 32 cores on mobile devices, so keep 345 * everything simple. 346 */ 347 typedef struct { 348 uint32_t mask; 349 } CpuList; 350 351 static __inline__ void 352 cpulist_init(CpuList* list) { 353 list->mask = 0; 354 } 355 356 static __inline__ void 357 cpulist_and(CpuList* list1, CpuList* list2) { 358 list1->mask &= list2->mask; 359 } 360 361 static __inline__ void 362 cpulist_set(CpuList* list, int index) { 363 if ((unsigned)index < 32) { 364 list->mask |= (uint32_t)(1U << index); 365 } 366 } 367 368 static __inline__ int 369 cpulist_count(CpuList* list) { 370 return __builtin_popcount(list->mask); 371 } 372 373 /* Parse a textual list of cpus and store the result inside a CpuList object. 374 * Input format is the following: 375 * - comma-separated list of items (no spaces) 376 * - each item is either a single decimal number (cpu index), or a range made 377 * of two numbers separated by a single dash (-). Ranges are inclusive. 378 * 379 * Examples: 0 380 * 2,4-127,128-143 381 * 0-1 382 */ 383 static void 384 cpulist_parse(CpuList* list, const char* line, int line_len) 385 { 386 const char* p = line; 387 const char* end = p + line_len; 388 const char* q; 389 390 /* NOTE: the input line coming from sysfs typically contains a 391 * trailing newline, so take care of it in the code below 392 */ 393 while (p < end && *p != '\n') 394 { 395 int val, start_value, end_value; 396 397 /* Find the end of current item, and put it into 'q' */ 398 q = memchr(p, ',', end-p); 399 if (q == NULL) { 400 q = end; 401 } 402 403 /* Get first value */ 404 p = parse_decimal(p, q, &start_value); 405 if (p == NULL) 406 goto BAD_FORMAT; 407 408 end_value = start_value; 409 410 /* If we're not at the end of the item, expect a dash and 411 * and integer; extract end value. 412 */ 413 if (p < q && *p == '-') { 414 p = parse_decimal(p+1, q, &end_value); 415 if (p == NULL) 416 goto BAD_FORMAT; 417 } 418 419 /* Set bits CPU list bits */ 420 for (val = start_value; val <= end_value; val++) { 421 cpulist_set(list, val); 422 } 423 424 /* Jump to next item */ 425 p = q; 426 if (p < end) 427 p++; 428 } 429 430 BAD_FORMAT: 431 ; 432 } 433 434 /* Read a CPU list from one sysfs file */ 435 static void 436 cpulist_read_from(CpuList* list, const char* filename) 437 { 438 char file[64]; 439 int filelen; 440 441 cpulist_init(list); 442 443 filelen = read_file(filename, file, sizeof file); 444 if (filelen < 0) { 445 D("Could not read %s: %s\n", filename, strerror(errno)); 446 return; 447 } 448 449 cpulist_parse(list, file, filelen); 450 } 451 #if defined(__aarch64__) 452 // see <uapi/asm/hwcap.h> kernel header 453 #define HWCAP_FP (1 << 0) 454 #define HWCAP_ASIMD (1 << 1) 455 #define HWCAP_AES (1 << 3) 456 #define HWCAP_PMULL (1 << 4) 457 #define HWCAP_SHA1 (1 << 5) 458 #define HWCAP_SHA2 (1 << 6) 459 #define HWCAP_CRC32 (1 << 7) 460 #endif 461 462 #if defined(__arm__) 463 464 // See <asm/hwcap.h> kernel header. 465 #define HWCAP_VFP (1 << 6) 466 #define HWCAP_IWMMXT (1 << 9) 467 #define HWCAP_NEON (1 << 12) 468 #define HWCAP_VFPv3 (1 << 13) 469 #define HWCAP_VFPv3D16 (1 << 14) 470 #define HWCAP_VFPv4 (1 << 16) 471 #define HWCAP_IDIVA (1 << 17) 472 #define HWCAP_IDIVT (1 << 18) 473 474 // see <uapi/asm/hwcap.h> kernel header 475 #define HWCAP2_AES (1 << 0) 476 #define HWCAP2_PMULL (1 << 1) 477 #define HWCAP2_SHA1 (1 << 2) 478 #define HWCAP2_SHA2 (1 << 3) 479 #define HWCAP2_CRC32 (1 << 4) 480 481 // This is the list of 32-bit ARMv7 optional features that are _always_ 482 // supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference 483 // Manual. 484 #define HWCAP_SET_FOR_ARMV8 \ 485 ( HWCAP_VFP | \ 486 HWCAP_NEON | \ 487 HWCAP_VFPv3 | \ 488 HWCAP_VFPv4 | \ 489 HWCAP_IDIVA | \ 490 HWCAP_IDIVT ) 491 #endif 492 493 #if defined(__mips__) 494 // see <uapi/asm/hwcap.h> kernel header 495 #define HWCAP_MIPS_R6 (1 << 0) 496 #define HWCAP_MIPS_MSA (1 << 1) 497 #endif 498 499 #if defined(__arm__) || defined(__aarch64__) || defined(__mips__) 500 501 #define AT_HWCAP 16 502 #define AT_HWCAP2 26 503 504 // Probe the system's C library for a 'getauxval' function and call it if 505 // it exits, or return 0 for failure. This function is available since API 506 // level 20. 507 // 508 // This code does *NOT* check for '__ANDROID_API__ >= 20' to support the 509 // edge case where some NDK developers use headers for a platform that is 510 // newer than the one really targetted by their application. 511 // This is typically done to use newer native APIs only when running on more 512 // recent Android versions, and requires careful symbol management. 513 // 514 // Note that getauxval() can't really be re-implemented here, because 515 // its implementation does not parse /proc/self/auxv. Instead it depends 516 // on values that are passed by the kernel at process-init time to the 517 // C runtime initialization layer. 518 static uint32_t 519 get_elf_hwcap_from_getauxval(int hwcap_type) { 520 typedef unsigned long getauxval_func_t(unsigned long); 521 522 dlerror(); 523 void* libc_handle = dlopen("libc.so", RTLD_NOW); 524 if (!libc_handle) { 525 D("Could not dlopen() C library: %s\n", dlerror()); 526 return 0; 527 } 528 529 uint32_t ret = 0; 530 getauxval_func_t* func = (getauxval_func_t*) 531 dlsym(libc_handle, "getauxval"); 532 if (!func) { 533 D("Could not find getauxval() in C library\n"); 534 } else { 535 // Note: getauxval() returns 0 on failure. Doesn't touch errno. 536 ret = (uint32_t)(*func)(hwcap_type); 537 } 538 dlclose(libc_handle); 539 return ret; 540 } 541 #endif 542 543 #if defined(__arm__) 544 // Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the 545 // current CPU. Note that this file is not accessible from regular 546 // application processes on some Android platform releases. 547 // On success, return new ELF hwcaps, or 0 on failure. 548 static uint32_t 549 get_elf_hwcap_from_proc_self_auxv(void) { 550 const char filepath[] = "/proc/self/auxv"; 551 int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY)); 552 if (fd < 0) { 553 D("Could not open %s: %s\n", filepath, strerror(errno)); 554 return 0; 555 } 556 557 struct { uint32_t tag; uint32_t value; } entry; 558 559 uint32_t result = 0; 560 for (;;) { 561 int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry)); 562 if (ret < 0) { 563 D("Error while reading %s: %s\n", filepath, strerror(errno)); 564 break; 565 } 566 // Detect end of list. 567 if (ret == 0 || (entry.tag == 0 && entry.value == 0)) 568 break; 569 if (entry.tag == AT_HWCAP) { 570 result = entry.value; 571 break; 572 } 573 } 574 close(fd); 575 return result; 576 } 577 578 /* Compute the ELF HWCAP flags from the content of /proc/cpuinfo. 579 * This works by parsing the 'Features' line, which lists which optional 580 * features the device's CPU supports, on top of its reference 581 * architecture. 582 */ 583 static uint32_t 584 get_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) { 585 uint32_t hwcaps = 0; 586 long architecture = 0; 587 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); 588 if (cpuArch) { 589 architecture = strtol(cpuArch, NULL, 10); 590 free(cpuArch); 591 592 if (architecture >= 8L) { 593 // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel. 594 // The 'Features' line only lists the optional features that the 595 // device's CPU supports, compared to its reference architecture 596 // which are of no use for this process. 597 D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture); 598 return HWCAP_SET_FOR_ARMV8; 599 } 600 } 601 602 char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); 603 if (cpuFeatures != NULL) { 604 D("Found cpuFeatures = '%s'\n", cpuFeatures); 605 606 if (has_list_item(cpuFeatures, "vfp")) 607 hwcaps |= HWCAP_VFP; 608 if (has_list_item(cpuFeatures, "vfpv3")) 609 hwcaps |= HWCAP_VFPv3; 610 if (has_list_item(cpuFeatures, "vfpv3d16")) 611 hwcaps |= HWCAP_VFPv3D16; 612 if (has_list_item(cpuFeatures, "vfpv4")) 613 hwcaps |= HWCAP_VFPv4; 614 if (has_list_item(cpuFeatures, "neon")) 615 hwcaps |= HWCAP_NEON; 616 if (has_list_item(cpuFeatures, "idiva")) 617 hwcaps |= HWCAP_IDIVA; 618 if (has_list_item(cpuFeatures, "idivt")) 619 hwcaps |= HWCAP_IDIVT; 620 if (has_list_item(cpuFeatures, "idiv")) 621 hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT; 622 if (has_list_item(cpuFeatures, "iwmmxt")) 623 hwcaps |= HWCAP_IWMMXT; 624 625 free(cpuFeatures); 626 } 627 return hwcaps; 628 } 629 #endif /* __arm__ */ 630 631 /* Return the number of cpus present on a given device. 632 * 633 * To handle all weird kernel configurations, we need to compute the 634 * intersection of the 'present' and 'possible' CPU lists and count 635 * the result. 636 */ 637 static int 638 get_cpu_count(void) 639 { 640 CpuList cpus_present[1]; 641 CpuList cpus_possible[1]; 642 643 cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present"); 644 cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible"); 645 646 /* Compute the intersection of both sets to get the actual number of 647 * CPU cores that can be used on this device by the kernel. 648 */ 649 cpulist_and(cpus_present, cpus_possible); 650 651 return cpulist_count(cpus_present); 652 } 653 654 static void 655 android_cpuInitFamily(void) 656 { 657 #if defined(__arm__) 658 g_cpuFamily = ANDROID_CPU_FAMILY_ARM; 659 #elif defined(__i386__) 660 g_cpuFamily = ANDROID_CPU_FAMILY_X86; 661 #elif defined(__mips64) 662 /* Needs to be before __mips__ since the compiler defines both */ 663 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64; 664 #elif defined(__mips__) 665 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS; 666 #elif defined(__aarch64__) 667 g_cpuFamily = ANDROID_CPU_FAMILY_ARM64; 668 #elif defined(__x86_64__) 669 g_cpuFamily = ANDROID_CPU_FAMILY_X86_64; 670 #else 671 g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN; 672 #endif 673 } 674 675 static void 676 android_cpuInit(void) 677 { 678 char* cpuinfo = NULL; 679 int cpuinfo_len; 680 681 android_cpuInitFamily(); 682 683 g_cpuFeatures = 0; 684 g_cpuCount = 1; 685 g_inited = 1; 686 687 cpuinfo_len = get_file_size("/proc/cpuinfo"); 688 if (cpuinfo_len < 0) { 689 D("cpuinfo_len cannot be computed!"); 690 return; 691 } 692 cpuinfo = malloc(cpuinfo_len); 693 if (cpuinfo == NULL) { 694 D("cpuinfo buffer could not be allocated"); 695 return; 696 } 697 cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len); 698 D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len, 699 cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo); 700 701 if (cpuinfo_len < 0) /* should not happen */ { 702 free(cpuinfo); 703 return; 704 } 705 706 /* Count the CPU cores, the value may be 0 for single-core CPUs */ 707 g_cpuCount = get_cpu_count(); 708 if (g_cpuCount == 0) { 709 g_cpuCount = 1; 710 } 711 712 D("found cpuCount = %d\n", g_cpuCount); 713 714 #ifdef __arm__ 715 { 716 /* Extract architecture from the "CPU Architecture" field. 717 * The list is well-known, unlike the the output of 718 * the 'Processor' field which can vary greatly. 719 * 720 * See the definition of the 'proc_arch' array in 721 * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in 722 * same file. 723 */ 724 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); 725 726 if (cpuArch != NULL) { 727 char* end; 728 long archNumber; 729 int hasARMv7 = 0; 730 731 D("found cpuArch = '%s'\n", cpuArch); 732 733 /* read the initial decimal number, ignore the rest */ 734 archNumber = strtol(cpuArch, &end, 10); 735 736 /* Note that ARMv8 is upwards compatible with ARMv7. */ 737 if (end > cpuArch && archNumber >= 7) { 738 hasARMv7 = 1; 739 } 740 741 /* Unfortunately, it seems that certain ARMv6-based CPUs 742 * report an incorrect architecture number of 7! 743 * 744 * See http://code.google.com/p/android/issues/detail?id=10812 745 * 746 * We try to correct this by looking at the 'elf_format' 747 * field reported by the 'Processor' field, which is of the 748 * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for 749 * an ARMv6-one. 750 */ 751 if (hasARMv7) { 752 char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len, 753 "Processor"); 754 if (cpuProc != NULL) { 755 D("found cpuProc = '%s'\n", cpuProc); 756 if (has_list_item(cpuProc, "(v6l)")) { 757 D("CPU processor and architecture mismatch!!\n"); 758 hasARMv7 = 0; 759 } 760 free(cpuProc); 761 } 762 } 763 764 if (hasARMv7) { 765 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; 766 } 767 768 /* The LDREX / STREX instructions are available from ARMv6 */ 769 if (archNumber >= 6) { 770 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; 771 } 772 773 free(cpuArch); 774 } 775 776 /* Extract the list of CPU features from ELF hwcaps */ 777 uint32_t hwcaps = 0; 778 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 779 if (!hwcaps) { 780 D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); 781 hwcaps = get_elf_hwcap_from_proc_self_auxv(); 782 } 783 if (!hwcaps) { 784 // Parsing /proc/self/auxv will fail from regular application 785 // processes on some Android platform versions, when this happens 786 // parse proc/cpuinfo instead. 787 D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n"); 788 hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len); 789 } 790 791 if (hwcaps != 0) { 792 int has_vfp = (hwcaps & HWCAP_VFP); 793 int has_vfpv3 = (hwcaps & HWCAP_VFPv3); 794 int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16); 795 int has_vfpv4 = (hwcaps & HWCAP_VFPv4); 796 int has_neon = (hwcaps & HWCAP_NEON); 797 int has_idiva = (hwcaps & HWCAP_IDIVA); 798 int has_idivt = (hwcaps & HWCAP_IDIVT); 799 int has_iwmmxt = (hwcaps & HWCAP_IWMMXT); 800 801 // The kernel does a poor job at ensuring consistency when 802 // describing CPU features. So lots of guessing is needed. 803 804 // 'vfpv4' implies VFPv3|VFP_FMA|FP16 805 if (has_vfpv4) 806 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 807 ANDROID_CPU_ARM_FEATURE_VFP_FP16 | 808 ANDROID_CPU_ARM_FEATURE_VFP_FMA; 809 810 // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC, 811 // a value of 'vfpv3' doesn't necessarily mean that the D32 812 // feature is present, so be conservative. All CPUs in the 813 // field that support D32 also support NEON, so this should 814 // not be a problem in practice. 815 if (has_vfpv3 || has_vfpv3d16) 816 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 817 818 // 'vfp' is super ambiguous. Depending on the kernel, it can 819 // either mean VFPv2 or VFPv3. Make it depend on ARMv7. 820 if (has_vfp) { 821 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7) 822 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 823 else 824 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2; 825 } 826 827 // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA 828 if (has_neon) { 829 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 830 ANDROID_CPU_ARM_FEATURE_NEON | 831 ANDROID_CPU_ARM_FEATURE_VFP_D32; 832 if (has_vfpv4) 833 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA; 834 } 835 836 // VFPv3 implies VFPv2 and ARMv7 837 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3) 838 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 | 839 ANDROID_CPU_ARM_FEATURE_ARMv7; 840 841 if (has_idiva) 842 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; 843 if (has_idivt) 844 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2; 845 846 if (has_iwmmxt) 847 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt; 848 } 849 850 /* Extract the list of CPU features from ELF hwcaps2 */ 851 uint32_t hwcaps2 = 0; 852 hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2); 853 if (hwcaps2 != 0) { 854 int has_aes = (hwcaps2 & HWCAP2_AES); 855 int has_pmull = (hwcaps2 & HWCAP2_PMULL); 856 int has_sha1 = (hwcaps2 & HWCAP2_SHA1); 857 int has_sha2 = (hwcaps2 & HWCAP2_SHA2); 858 int has_crc32 = (hwcaps2 & HWCAP2_CRC32); 859 860 if (has_aes) 861 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES; 862 if (has_pmull) 863 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL; 864 if (has_sha1) 865 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1; 866 if (has_sha2) 867 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2; 868 if (has_crc32) 869 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32; 870 } 871 /* Extract the cpuid value from various fields */ 872 // The CPUID value is broken up in several entries in /proc/cpuinfo. 873 // This table is used to rebuild it from the entries. 874 static const struct CpuIdEntry { 875 const char* field; 876 char format; 877 char bit_lshift; 878 char bit_length; 879 } cpu_id_entries[] = { 880 { "CPU implementer", 'x', 24, 8 }, 881 { "CPU variant", 'x', 20, 4 }, 882 { "CPU part", 'x', 4, 12 }, 883 { "CPU revision", 'd', 0, 4 }, 884 }; 885 size_t i; 886 D("Parsing /proc/cpuinfo to recover CPUID\n"); 887 for (i = 0; 888 i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]); 889 ++i) { 890 const struct CpuIdEntry* entry = &cpu_id_entries[i]; 891 char* value = extract_cpuinfo_field(cpuinfo, 892 cpuinfo_len, 893 entry->field); 894 if (value == NULL) 895 continue; 896 897 D("field=%s value='%s'\n", entry->field, value); 898 char* value_end = value + strlen(value); 899 int val = 0; 900 const char* start = value; 901 const char* p; 902 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { 903 start += 2; 904 p = parse_hexadecimal(start, value_end, &val); 905 } else if (entry->format == 'x') 906 p = parse_hexadecimal(value, value_end, &val); 907 else 908 p = parse_decimal(value, value_end, &val); 909 910 if (p > (const char*)start) { 911 val &= ((1 << entry->bit_length)-1); 912 val <<= entry->bit_lshift; 913 g_cpuIdArm |= (uint32_t) val; 914 } 915 916 free(value); 917 } 918 919 // Handle kernel configuration bugs that prevent the correct 920 // reporting of CPU features. 921 static const struct CpuFix { 922 uint32_t cpuid; 923 uint64_t or_flags; 924 } cpu_fixes[] = { 925 /* The Nexus 4 (Qualcomm Krait) kernel configuration 926 * forgets to report IDIV support. */ 927 { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM | 928 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 }, 929 { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM | 930 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 }, 931 }; 932 size_t n; 933 for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) { 934 const struct CpuFix* entry = &cpu_fixes[n]; 935 936 if (g_cpuIdArm == entry->cpuid) 937 g_cpuFeatures |= entry->or_flags; 938 } 939 940 // Special case: The emulator-specific Android 4.2 kernel fails 941 // to report support for the 32-bit ARM IDIV instruction. 942 // Technically, this is a feature of the virtual CPU implemented 943 // by the emulator. Note that it could also support Thumb IDIV 944 // in the future, and this will have to be slightly updated. 945 char* hardware = extract_cpuinfo_field(cpuinfo, 946 cpuinfo_len, 947 "Hardware"); 948 if (hardware) { 949 if (!strcmp(hardware, "Goldfish") && 950 g_cpuIdArm == 0x4100c080 && 951 (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) { 952 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; 953 } 954 free(hardware); 955 } 956 } 957 #endif /* __arm__ */ 958 #ifdef __aarch64__ 959 { 960 /* Extract the list of CPU features from ELF hwcaps */ 961 uint32_t hwcaps = 0; 962 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 963 if (hwcaps != 0) { 964 int has_fp = (hwcaps & HWCAP_FP); 965 int has_asimd = (hwcaps & HWCAP_ASIMD); 966 int has_aes = (hwcaps & HWCAP_AES); 967 int has_pmull = (hwcaps & HWCAP_PMULL); 968 int has_sha1 = (hwcaps & HWCAP_SHA1); 969 int has_sha2 = (hwcaps & HWCAP_SHA2); 970 int has_crc32 = (hwcaps & HWCAP_CRC32); 971 972 if(has_fp == 0) { 973 D("ERROR: Floating-point unit missing, but is required by Android on AArch64 CPUs\n"); 974 } 975 if(has_asimd == 0) { 976 D("ERROR: ASIMD unit missing, but is required by Android on AArch64 CPUs\n"); 977 } 978 979 if (has_fp) 980 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP; 981 if (has_asimd) 982 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD; 983 if (has_aes) 984 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES; 985 if (has_pmull) 986 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL; 987 if (has_sha1) 988 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1; 989 if (has_sha2) 990 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2; 991 if (has_crc32) 992 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32; 993 } 994 } 995 #endif /* __aarch64__ */ 996 997 #if defined(__i386__) || defined(__x86_64__) 998 int regs[4]; 999 1000 /* According to http://en.wikipedia.org/wiki/CPUID */ 1001 #define VENDOR_INTEL_b 0x756e6547 1002 #define VENDOR_INTEL_c 0x6c65746e 1003 #define VENDOR_INTEL_d 0x49656e69 1004 1005 x86_cpuid(0, regs); 1006 int vendorIsIntel = (regs[1] == VENDOR_INTEL_b && 1007 regs[2] == VENDOR_INTEL_c && 1008 regs[3] == VENDOR_INTEL_d); 1009 1010 x86_cpuid(1, regs); 1011 if ((regs[2] & (1 << 9)) != 0) { 1012 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; 1013 } 1014 if ((regs[2] & (1 << 23)) != 0) { 1015 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; 1016 } 1017 if ((regs[2] & (1 << 19)) != 0) { 1018 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1; 1019 } 1020 if ((regs[2] & (1 << 20)) != 0) { 1021 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2; 1022 } 1023 if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) { 1024 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; 1025 } 1026 if ((regs[2] & (1 << 25)) != 0) { 1027 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI; 1028 } 1029 if ((regs[2] & (1 << 28)) != 0) { 1030 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX; 1031 } 1032 if ((regs[2] & (1 << 30)) != 0) { 1033 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND; 1034 } 1035 1036 x86_cpuid(7, regs); 1037 if ((regs[1] & (1 << 5)) != 0) { 1038 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2; 1039 } 1040 if ((regs[1] & (1 << 29)) != 0) { 1041 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI; 1042 } 1043 1044 1045 #endif 1046 #if defined( __mips__) 1047 { /* MIPS and MIPS64 */ 1048 /* Extract the list of CPU features from ELF hwcaps */ 1049 uint32_t hwcaps = 0; 1050 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 1051 if (hwcaps != 0) { 1052 int has_r6 = (hwcaps & HWCAP_MIPS_R6); 1053 int has_msa = (hwcaps & HWCAP_MIPS_MSA); 1054 if (has_r6) 1055 g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6; 1056 if (has_msa) 1057 g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA; 1058 } 1059 } 1060 #endif /* __mips__ */ 1061 1062 free(cpuinfo); 1063 } 1064 1065 1066 AndroidCpuFamily 1067 android_getCpuFamily(void) 1068 { 1069 pthread_once(&g_once, android_cpuInit); 1070 return g_cpuFamily; 1071 } 1072 1073 1074 uint64_t 1075 android_getCpuFeatures(void) 1076 { 1077 pthread_once(&g_once, android_cpuInit); 1078 return g_cpuFeatures; 1079 } 1080 1081 1082 int 1083 android_getCpuCount(void) 1084 { 1085 pthread_once(&g_once, android_cpuInit); 1086 return g_cpuCount; 1087 } 1088 1089 static void 1090 android_cpuInitDummy(void) 1091 { 1092 g_inited = 1; 1093 } 1094 1095 int 1096 android_setCpu(int cpu_count, uint64_t cpu_features) 1097 { 1098 /* Fail if the library was already initialized. */ 1099 if (g_inited) 1100 return 0; 1101 1102 android_cpuInitFamily(); 1103 g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count); 1104 g_cpuFeatures = cpu_features; 1105 pthread_once(&g_once, android_cpuInitDummy); 1106 1107 return 1; 1108 } 1109 1110 #ifdef __arm__ 1111 uint32_t 1112 android_getCpuIdArm(void) 1113 { 1114 pthread_once(&g_once, android_cpuInit); 1115 return g_cpuIdArm; 1116 } 1117 1118 int 1119 android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) 1120 { 1121 if (!android_setCpu(cpu_count, cpu_features)) 1122 return 0; 1123 1124 g_cpuIdArm = cpu_id; 1125 return 1; 1126 } 1127 #endif /* __arm__ */ 1128 1129 /* 1130 * Technical note: Making sense of ARM's FPU architecture versions. 1131 * 1132 * FPA was ARM's first attempt at an FPU architecture. There is no Android 1133 * device that actually uses it since this technology was already obsolete 1134 * when the project started. If you see references to FPA instructions 1135 * somewhere, you can be sure that this doesn't apply to Android at all. 1136 * 1137 * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of 1138 * new versions / additions to it. ARM considers this obsolete right now, 1139 * and no known Android device implements it either. 1140 * 1141 * VFPv2 added a few instructions to VFPv1, and is an *optional* extension 1142 * supported by some ARMv5TE, ARMv6 and ARMv6T2 CPUs. Note that a device 1143 * supporting the 'armeabi' ABI doesn't necessarily support these. 1144 * 1145 * VFPv3-D16 adds a few instructions on top of VFPv2 and is typically used 1146 * on ARMv7-A CPUs which implement a FPU. Note that it is also mandated 1147 * by the Android 'armeabi-v7a' ABI. The -D16 suffix in its name means 1148 * that it provides 16 double-precision FPU registers (d0-d15) and 32 1149 * single-precision ones (s0-s31) which happen to be mapped to the same 1150 * register banks. 1151 * 1152 * VFPv3-D32 is the name of an extension to VFPv3-D16 that provides 16 1153 * additional double precision registers (d16-d31). Note that there are 1154 * still only 32 single precision registers. 1155 * 1156 * VFPv3xD is a *subset* of VFPv3-D16 that only provides single-precision 1157 * registers. It is only used on ARMv7-M (i.e. on micro-controllers) which 1158 * are not supported by Android. Note that it is not compatible with VFPv2. 1159 * 1160 * NOTE: The term 'VFPv3' usually designate either VFPv3-D16 or VFPv3-D32 1161 * depending on context. For example GCC uses it for VFPv3-D32, but 1162 * the Linux kernel code uses it for VFPv3-D16 (especially in 1163 * /proc/cpuinfo). Always try to use the full designation when 1164 * possible. 1165 * 1166 * NEON, a.k.a. "ARM Advanced SIMD" is an extension that provides 1167 * instructions to perform parallel computations on vectors of 8, 16, 1168 * 32, 64 and 128 bit quantities. NEON requires VFPv32-D32 since all 1169 * NEON registers are also mapped to the same register banks. 1170 * 1171 * VFPv4-D16, adds a few instructions on top of VFPv3-D16 in order to 1172 * perform fused multiply-accumulate on VFP registers, as well as 1173 * half-precision (16-bit) conversion operations. 1174 * 1175 * VFPv4-D32 is VFPv4-D16 with 32, instead of 16, FPU double precision 1176 * registers. 1177 * 1178 * VPFv4-NEON is VFPv4-D32 with NEON instructions. It also adds fused 1179 * multiply-accumulate instructions that work on the NEON registers. 1180 * 1181 * NOTE: Similarly, "VFPv4" might either reference VFPv4-D16 or VFPv4-D32 1182 * depending on context. 1183 * 1184 * The following information was determined by scanning the binutils-2.22 1185 * sources: 1186 * 1187 * Basic VFP instruction subsets: 1188 * 1189 * #define FPU_VFP_EXT_V1xD 0x08000000 // Base VFP instruction set. 1190 * #define FPU_VFP_EXT_V1 0x04000000 // Double-precision insns. 1191 * #define FPU_VFP_EXT_V2 0x02000000 // ARM10E VFPr1. 1192 * #define FPU_VFP_EXT_V3xD 0x01000000 // VFPv3 single-precision. 1193 * #define FPU_VFP_EXT_V3 0x00800000 // VFPv3 double-precision. 1194 * #define FPU_NEON_EXT_V1 0x00400000 // Neon (SIMD) insns. 1195 * #define FPU_VFP_EXT_D32 0x00200000 // Registers D16-D31. 1196 * #define FPU_VFP_EXT_FP16 0x00100000 // Half-precision extensions. 1197 * #define FPU_NEON_EXT_FMA 0x00080000 // Neon fused multiply-add 1198 * #define FPU_VFP_EXT_FMA 0x00040000 // VFP fused multiply-add 1199 * 1200 * FPU types (excluding NEON) 1201 * 1202 * FPU_VFP_V1xD (EXT_V1xD) 1203 * | 1204 * +--------------------------+ 1205 * | | 1206 * FPU_VFP_V1 (+EXT_V1) FPU_VFP_V3xD (+EXT_V2+EXT_V3xD) 1207 * | | 1208 * | | 1209 * FPU_VFP_V2 (+EXT_V2) FPU_VFP_V4_SP_D16 (+EXT_FP16+EXT_FMA) 1210 * | 1211 * FPU_VFP_V3D16 (+EXT_Vx3D+EXT_V3) 1212 * | 1213 * +--------------------------+ 1214 * | | 1215 * FPU_VFP_V3 (+EXT_D32) FPU_VFP_V4D16 (+EXT_FP16+EXT_FMA) 1216 * | | 1217 * | FPU_VFP_V4 (+EXT_D32) 1218 * | 1219 * FPU_VFP_HARD (+EXT_FMA+NEON_EXT_FMA) 1220 * 1221 * VFP architectures: 1222 * 1223 * ARCH_VFP_V1xD (EXT_V1xD) 1224 * | 1225 * +------------------+ 1226 * | | 1227 * | ARCH_VFP_V3xD (+EXT_V2+EXT_V3xD) 1228 * | | 1229 * | ARCH_VFP_V3xD_FP16 (+EXT_FP16) 1230 * | | 1231 * | ARCH_VFP_V4_SP_D16 (+EXT_FMA) 1232 * | 1233 * ARCH_VFP_V1 (+EXT_V1) 1234 * | 1235 * ARCH_VFP_V2 (+EXT_V2) 1236 * | 1237 * ARCH_VFP_V3D16 (+EXT_V3xD+EXT_V3) 1238 * | 1239 * +-------------------+ 1240 * | | 1241 * | ARCH_VFP_V3D16_FP16 (+EXT_FP16) 1242 * | 1243 * +-------------------+ 1244 * | | 1245 * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA) 1246 * | | 1247 * | ARCH_VFP_V4 (+EXT_D32) 1248 * | | 1249 * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA) 1250 * | 1251 * ARCH_VFP_V3 (+EXT_D32) 1252 * | 1253 * +-------------------+ 1254 * | | 1255 * | ARCH_VFP_V3_FP16 (+EXT_FP16) 1256 * | 1257 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON) 1258 * | 1259 * ARCH_NEON_FP16 (+EXT_FP16) 1260 * 1261 * -fpu=<name> values and their correspondance with FPU architectures above: 1262 * 1263 * {"vfp", FPU_ARCH_VFP_V2}, 1264 * {"vfp9", FPU_ARCH_VFP_V2}, 1265 * {"vfp3", FPU_ARCH_VFP_V3}, // For backwards compatbility. 1266 * {"vfp10", FPU_ARCH_VFP_V2}, 1267 * {"vfp10-r0", FPU_ARCH_VFP_V1}, 1268 * {"vfpxd", FPU_ARCH_VFP_V1xD}, 1269 * {"vfpv2", FPU_ARCH_VFP_V2}, 1270 * {"vfpv3", FPU_ARCH_VFP_V3}, 1271 * {"vfpv3-fp16", FPU_ARCH_VFP_V3_FP16}, 1272 * {"vfpv3-d16", FPU_ARCH_VFP_V3D16}, 1273 * {"vfpv3-d16-fp16", FPU_ARCH_VFP_V3D16_FP16}, 1274 * {"vfpv3xd", FPU_ARCH_VFP_V3xD}, 1275 * {"vfpv3xd-fp16", FPU_ARCH_VFP_V3xD_FP16}, 1276 * {"neon", FPU_ARCH_VFP_V3_PLUS_NEON_V1}, 1277 * {"neon-fp16", FPU_ARCH_NEON_FP16}, 1278 * {"vfpv4", FPU_ARCH_VFP_V4}, 1279 * {"vfpv4-d16", FPU_ARCH_VFP_V4D16}, 1280 * {"fpv4-sp-d16", FPU_ARCH_VFP_V4_SP_D16}, 1281 * {"neon-vfpv4", FPU_ARCH_NEON_VFP_V4}, 1282 * 1283 * 1284 * Simplified diagram that only includes FPUs supported by Android: 1285 * Only ARCH_VFP_V3D16 is actually mandated by the armeabi-v7a ABI, 1286 * all others are optional and must be probed at runtime. 1287 * 1288 * ARCH_VFP_V3D16 (EXT_V1xD+EXT_V1+EXT_V2+EXT_V3xD+EXT_V3) 1289 * | 1290 * +-------------------+ 1291 * | | 1292 * | ARCH_VFP_V3D16_FP16 (+EXT_FP16) 1293 * | 1294 * +-------------------+ 1295 * | | 1296 * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA) 1297 * | | 1298 * | ARCH_VFP_V4 (+EXT_D32) 1299 * | | 1300 * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA) 1301 * | 1302 * ARCH_VFP_V3 (+EXT_D32) 1303 * | 1304 * +-------------------+ 1305 * | | 1306 * | ARCH_VFP_V3_FP16 (+EXT_FP16) 1307 * | 1308 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON) 1309 * | 1310 * ARCH_NEON_FP16 (+EXT_FP16) 1311 * 1312 */ 1313