long sysconf(int name) { switch (name) { // // Things we actually have to calculate... // case _SC_ARG_MAX: // Not a constant since Linux 2.6.23; see fs/exec.c for details. // At least 32 pages, otherwise a quarter of the stack limit. return MAX(__sysconf_rlimit(RLIMIT_STACK) / 4, _KERNEL_ARG_MAX); case _SC_AVPHYS_PAGES: return get_avphys_pages(); case _SC_CHILD_MAX: return __sysconf_rlimit(RLIMIT_NPROC); case _SC_CLK_TCK: return static_cast<long>(getauxval(AT_CLKTCK)); case _SC_NPROCESSORS_CONF: return get_nprocs_conf(); case _SC_NPROCESSORS_ONLN: return get_nprocs(); case _SC_OPEN_MAX: return __sysconf_rlimit(RLIMIT_NOFILE); case _SC_PAGESIZE: case _SC_PAGE_SIZE: // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value. return static_cast<long>(getauxval(AT_PAGESZ)); case _SC_PHYS_PAGES: return get_phys_pages(); // // Constants... // case _SC_BC_BASE_MAX: return _POSIX2_BC_BASE_MAX; // Minimum requirement. case _SC_BC_DIM_MAX: return _POSIX2_BC_DIM_MAX; // Minimum requirement. case _SC_BC_SCALE_MAX: return _POSIX2_BC_SCALE_MAX; // Minimum requirement. case _SC_BC_STRING_MAX: return _POSIX2_BC_STRING_MAX; // Minimum requirement. case _SC_COLL_WEIGHTS_MAX: return _POSIX2_COLL_WEIGHTS_MAX; // Minimum requirement. case _SC_EXPR_NEST_MAX: return _POSIX2_EXPR_NEST_MAX; // Minimum requirement. case _SC_LINE_MAX: return _POSIX2_LINE_MAX; // Minimum requirement. case _SC_NGROUPS_MAX: return NGROUPS_MAX; case _SC_PASS_MAX: return PASS_MAX; case _SC_2_C_BIND: return _POSIX2_C_BIND; case _SC_2_C_DEV: return _POSIX2_C_DEV; case _SC_2_CHAR_TERM: return _POSIX2_CHAR_TERM; case _SC_2_FORT_DEV: return -1; case _SC_2_FORT_RUN: return -1; case _SC_2_LOCALEDEF: return _POSIX2_LOCALEDEF; case _SC_2_SW_DEV: return _POSIX2_SW_DEV; case _SC_2_UPE: return _POSIX2_UPE; case _SC_2_VERSION: return _POSIX2_VERSION; case _SC_JOB_CONTROL: return _POSIX_JOB_CONTROL; case _SC_SAVED_IDS: return _POSIX_SAVED_IDS; case _SC_VERSION: return _POSIX_VERSION; case _SC_RE_DUP_MAX: return _POSIX_RE_DUP_MAX; // Minimum requirement. case _SC_STREAM_MAX: return FOPEN_MAX; case _SC_TZNAME_MAX: return _POSIX_TZNAME_MAX; // Minimum requirement. case _SC_XOPEN_CRYPT: return _XOPEN_CRYPT; case _SC_XOPEN_ENH_I18N: return _XOPEN_ENH_I18N; case _SC_XOPEN_SHM: return _XOPEN_SHM; case _SC_XOPEN_VERSION: return _XOPEN_VERSION; case _SC_XOPEN_REALTIME: return _XOPEN_REALTIME; case _SC_XOPEN_REALTIME_THREADS: return _XOPEN_REALTIME_THREADS; case _SC_XOPEN_LEGACY: return _XOPEN_LEGACY; case _SC_ATEXIT_MAX: return LONG_MAX; // Unlimited. case _SC_IOV_MAX: return IOV_MAX; case _SC_XOPEN_UNIX: return _XOPEN_UNIX; case _SC_AIO_LISTIO_MAX: return _POSIX_AIO_LISTIO_MAX; // Minimum requirement. case _SC_AIO_MAX: return _POSIX_AIO_MAX; // Minimum requirement. case _SC_AIO_PRIO_DELTA_MAX:return 0; // Minimum requirement. case _SC_DELAYTIMER_MAX: return INT_MAX; case _SC_MQ_OPEN_MAX: return _POSIX_MQ_OPEN_MAX; // Minimum requirement. case _SC_MQ_PRIO_MAX: return _POSIX_MQ_PRIO_MAX; // Minimum requirement. case _SC_RTSIG_MAX: return RTSIG_MAX; case _SC_SEM_NSEMS_MAX: return _POSIX_SEM_NSEMS_MAX; // Minimum requirement. case _SC_SEM_VALUE_MAX: return SEM_VALUE_MAX; case _SC_SIGQUEUE_MAX: return _POSIX_SIGQUEUE_MAX; // Minimum requirement. case _SC_TIMER_MAX: return _POSIX_TIMER_MAX; // Minimum requirement. case _SC_ASYNCHRONOUS_IO: return _POSIX_ASYNCHRONOUS_IO; case _SC_FSYNC: return _POSIX_FSYNC; case _SC_MAPPED_FILES: return _POSIX_MAPPED_FILES; case _SC_MEMLOCK: return _POSIX_MEMLOCK; case _SC_MEMLOCK_RANGE: return _POSIX_MEMLOCK_RANGE; case _SC_MEMORY_PROTECTION: return _POSIX_MEMORY_PROTECTION; case _SC_MESSAGE_PASSING: return _POSIX_MESSAGE_PASSING; case _SC_PRIORITIZED_IO: return _POSIX_PRIORITIZED_IO; case _SC_PRIORITY_SCHEDULING: return _POSIX_PRIORITY_SCHEDULING; case _SC_REALTIME_SIGNALS: return _POSIX_REALTIME_SIGNALS; case _SC_SEMAPHORES: return _POSIX_SEMAPHORES; case _SC_SHARED_MEMORY_OBJECTS: return _POSIX_SHARED_MEMORY_OBJECTS; case _SC_SYNCHRONIZED_IO: return _POSIX_SYNCHRONIZED_IO; case _SC_TIMERS: return _POSIX_TIMERS; case _SC_GETGR_R_SIZE_MAX: return 1024; case _SC_GETPW_R_SIZE_MAX: return 1024; case _SC_LOGIN_NAME_MAX: return 256; // Seems default on linux. case _SC_THREAD_DESTRUCTOR_ITERATIONS: return PTHREAD_DESTRUCTOR_ITERATIONS; case _SC_THREAD_KEYS_MAX: return PTHREAD_KEYS_MAX; case _SC_THREAD_STACK_MIN: return PTHREAD_STACK_MIN; case _SC_THREAD_THREADS_MAX: return -1; // No specific limit. case _SC_TTY_NAME_MAX: return 32; // Seems default on linux. case _SC_THREADS: return _POSIX_THREADS; case _SC_THREAD_ATTR_STACKADDR: return _POSIX_THREAD_ATTR_STACKADDR; case _SC_THREAD_ATTR_STACKSIZE: return _POSIX_THREAD_ATTR_STACKSIZE; case _SC_THREAD_PRIORITY_SCHEDULING: return _POSIX_THREAD_PRIORITY_SCHEDULING; case _SC_THREAD_PRIO_INHERIT: return _POSIX_THREAD_PRIO_INHERIT; case _SC_THREAD_PRIO_PROTECT: return _POSIX_THREAD_PRIO_PROTECT; case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS; case _SC_MONOTONIC_CLOCK: return _POSIX_VERSION; case _SC_2_PBS: return -1; // Obsolescent in POSIX.1-2008. case _SC_2_PBS_ACCOUNTING: return -1; // Obsolescent in POSIX.1-2008. case _SC_2_PBS_CHECKPOINT: return -1; // Obsolescent in POSIX.1-2008. case _SC_2_PBS_LOCATE: return -1; // Obsolescent in POSIX.1-2008. case _SC_2_PBS_MESSAGE: return -1; // Obsolescent in POSIX.1-2008. case _SC_2_PBS_TRACK: return -1; // Obsolescent in POSIX.1-2008. case _SC_ADVISORY_INFO: return _POSIX_ADVISORY_INFO; case _SC_BARRIERS: return _POSIX_BARRIERS; case _SC_CLOCK_SELECTION: return _POSIX_CLOCK_SELECTION; case _SC_CPUTIME: return _POSIX_VERSION; case _SC_HOST_NAME_MAX: return _POSIX_HOST_NAME_MAX; // Minimum requirement. case _SC_IPV6: return _POSIX_IPV6; case _SC_RAW_SOCKETS: return _POSIX_RAW_SOCKETS; case _SC_READER_WRITER_LOCKS: return _POSIX_READER_WRITER_LOCKS; case _SC_REGEXP: return _POSIX_REGEXP; case _SC_SHELL: return _POSIX_SHELL; case _SC_SPAWN: return _POSIX_SPAWN; case _SC_SPIN_LOCKS: return _POSIX_SPIN_LOCKS; case _SC_SPORADIC_SERVER: return _POSIX_SPORADIC_SERVER; case _SC_SS_REPL_MAX: return -1; case _SC_SYMLOOP_MAX: return _POSIX_SYMLOOP_MAX; // Minimum requirement. case _SC_THREAD_CPUTIME: return _POSIX_VERSION; case _SC_THREAD_PROCESS_SHARED: return _POSIX_THREAD_PROCESS_SHARED; case _SC_THREAD_ROBUST_PRIO_INHERIT: return _POSIX_THREAD_ROBUST_PRIO_INHERIT; case _SC_THREAD_ROBUST_PRIO_PROTECT: return _POSIX_THREAD_ROBUST_PRIO_PROTECT; case _SC_THREAD_SPORADIC_SERVER: return _POSIX_THREAD_SPORADIC_SERVER; case _SC_TIMEOUTS: return _POSIX_TIMEOUTS; case _SC_TRACE: return -1; // Obsolescent in POSIX.1-2008. case _SC_TRACE_EVENT_FILTER: return -1; // Obsolescent in POSIX.1-2008. case _SC_TRACE_EVENT_NAME_MAX: return -1; case _SC_TRACE_INHERIT: return -1; // Obsolescent in POSIX.1-2008. case _SC_TRACE_LOG: return -1; // Obsolescent in POSIX.1-2008. case _SC_TRACE_NAME_MAX: return -1; case _SC_TRACE_SYS_MAX: return -1; case _SC_TRACE_USER_EVENT_MAX: return -1; case _SC_TYPED_MEMORY_OBJECTS: return _POSIX_TYPED_MEMORY_OBJECTS; case _SC_V7_ILP32_OFF32: return _POSIX_V7_ILP32_OFF32; case _SC_V7_ILP32_OFFBIG: return _POSIX_V7_ILP32_OFFBIG; case _SC_V7_LP64_OFF64: return _POSIX_V7_LP64_OFF64; case _SC_V7_LPBIG_OFFBIG: return _POSIX_V7_LPBIG_OFFBIG; case _SC_XOPEN_STREAMS: return -1; // Obsolescent in POSIX.1-2008. case _SC_XOPEN_UUCP: return -1; // We do not have actual implementations for cache queries. // It's valid to return 0 as the result is unknown. case _SC_LEVEL1_ICACHE_SIZE: return 0; case _SC_LEVEL1_ICACHE_ASSOC: return 0; case _SC_LEVEL1_ICACHE_LINESIZE: return 0; case _SC_LEVEL1_DCACHE_SIZE: return 0; case _SC_LEVEL1_DCACHE_ASSOC: return 0; case _SC_LEVEL1_DCACHE_LINESIZE: return 0; case _SC_LEVEL2_CACHE_SIZE: return 0; case _SC_LEVEL2_CACHE_ASSOC: return 0; case _SC_LEVEL2_CACHE_LINESIZE: return 0; case _SC_LEVEL3_CACHE_SIZE: return 0; case _SC_LEVEL3_CACHE_ASSOC: return 0; case _SC_LEVEL3_CACHE_LINESIZE: return 0; case _SC_LEVEL4_CACHE_SIZE: return 0; case _SC_LEVEL4_CACHE_ASSOC: return 0; case _SC_LEVEL4_CACHE_LINESIZE: return 0; default: // Posix says EINVAL is the only error that shall be returned, // but glibc uses ENOSYS. errno = ENOSYS; return -1; } }
int main (int argc, char* argv[]) { char parent_process_path_buf[128]; sprintf(parent_process_path_buf, "/proc/%d/cmdline", getppid()); std::ifstream parent_cmdline; parent_cmdline.open(parent_process_path_buf); std::string parent_cmdline_str; std::getline(parent_cmdline, parent_cmdline_str); parent_cmdline.close(); std::cout <<(char *)getauxval(AT_EXECFN) << " pid " << getpid() << " Parent PID is " << getppid() << " " <<parent_cmdline_str << " " <<currentDateTime() << std::endl; usleep(1000000* (rand()%10+1)); std::cout <<get_process_name(getpid()) << " pid " << getpid() << " Parent PID is " << getppid() << " " <<parent_cmdline_str << " " <<currentDateTime() << std::endl; std::cout << "Resource size is " << (size_t)&_binary_main_cpp_size<<std::endl; std::string src(&_binary_main_cpp_start,(size_t)( &_binary_main_cpp_end-&_binary_main_cpp_start)); ACE_Argv_Type_Converter to_tchar (argc, argv); ACE_Get_Opt get_opt (argc, to_tchar.get_TCHAR_argv (), ACE_TEXT ("msad:"), 1, 0); //ACE_Get_Opt get_opt (argc,argv, ACE_TEXT ("P"), 1, 0); for (int c; (c = get_opt ()) != -1; ) switch (c) { case 's': // print source code std::cout <<src << std::endl; break; case 'm': // print free memory information { std::cout << "Parent process is " << get_process_name(getppid()) << std::endl; std::string ss=runcmd("free -m"); std::cout << ss <<std::endl; } break; case 'a': // test ACE_Argv_Type_Converter { ACE_ARGV_T<char> argslist; argslist.add("abc def ghi"); argslist.add("4th"); argslist.add("5th"); int newargc=argslist.argc(); ACE_Argv_Type_Converter cmdline(newargc, argslist.argv()); char** newargs=cmdline.get_ASCII_argv(); std::cout << "arg count " << argslist.argc()<<std::endl; for(int i=0; i<newargc;i++) std::cout<< "argv["<<i<<"] " << newargs[i]<<std::endl; } break; case 'd': // compare performance of itoa and sprintf { int cnt = ACE_OS::atoi(get_opt.opt_arg ()); uint64_t perf1start= getCurrentMillis(); char buf[16]; for(int i=0; i<cnt; i++) itoa(i, buf, 10); uint64_t perf2start= getCurrentMillis(); for(int i=0; i<cnt; i++) sprintf(buf, "%d", i); uint64_t perf2stop= getCurrentMillis(); std::cout << "convert "<<cnt<<" int to string by itoa in " << (perf2start-perf1start) << " milliseconds, sprintf in " << (perf2stop-perf2start) << " milliseconds\n"; } break; default: break; } return 0; }
void OPENSSL_cpuid_setup(void) { char *e; struct sigaction ill_oact, ill_act; sigset_t oset; static int trigger = 0; if (trigger) return; trigger = 1; if ((e = getenv("OPENSSL_armcap"))) { OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); return; } sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); sigdelset(&all_masked, SIGTRAP); sigdelset(&all_masked, SIGFPE); sigdelset(&all_masked, SIGBUS); sigdelset(&all_masked, SIGSEGV); OPENSSL_armcap_P = 0; memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); if (getauxval != NULL) { if (getauxval(HWCAP) & HWCAP_NEON) { unsigned long hwcap = getauxval(HWCAP_CE); OPENSSL_armcap_P |= ARMV7_NEON; if (hwcap & HWCAP_CE_AES) OPENSSL_armcap_P |= ARMV8_AES; if (hwcap & HWCAP_CE_PMULL) OPENSSL_armcap_P |= ARMV8_PMULL; if (hwcap & HWCAP_CE_SHA1) OPENSSL_armcap_P |= ARMV8_SHA1; if (hwcap & HWCAP_CE_SHA256) OPENSSL_armcap_P |= ARMV8_SHA256; } } else if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_neon_probe(); OPENSSL_armcap_P |= ARMV7_NEON; if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_pmull_probe(); OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; } else if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_aes_probe(); OPENSSL_armcap_P |= ARMV8_AES; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha1_probe(); OPENSSL_armcap_P |= ARMV8_SHA1; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha256_probe(); OPENSSL_armcap_P |= ARMV8_SHA256; } } if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_tick(); OPENSSL_armcap_P |= ARMV7_TICK; } sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); }
void OPENSSL_cpuid_setup(void) { const char *e; struct sigaction ill_oact, ill_act; sigset_t oset; static int trigger = 0; if (trigger) return; trigger = 1; if ((e = getenv("OPENSSL_armcap"))) { OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); return; } # if defined(__APPLE__) && !defined(__aarch64__) /* * Capability probing by catching SIGILL appears to be problematic * on iOS. But since Apple universe is "monocultural", it's actually * possible to simply set pre-defined processor capability mask. */ if (1) { OPENSSL_armcap_P = ARMV7_NEON; return; } /* * One could do same even for __aarch64__ iOS builds. It's not done * exclusively for reasons of keeping code unified across platforms. * Unified code works because it never triggers SIGILL on Apple * devices... */ # endif OPENSSL_armcap_P = 0; # ifdef OSSL_IMPLEMENT_GETAUXVAL if (getauxval(HWCAP) & HWCAP_NEON) { unsigned long hwcap = getauxval(HWCAP_CE); OPENSSL_armcap_P |= ARMV7_NEON; if (hwcap & HWCAP_CE_AES) OPENSSL_armcap_P |= ARMV8_AES; if (hwcap & HWCAP_CE_PMULL) OPENSSL_armcap_P |= ARMV8_PMULL; if (hwcap & HWCAP_CE_SHA1) OPENSSL_armcap_P |= ARMV8_SHA1; if (hwcap & HWCAP_CE_SHA256) OPENSSL_armcap_P |= ARMV8_SHA256; # ifdef __aarch64__ if (hwcap & HWCAP_CE_SHA512) OPENSSL_armcap_P |= ARMV8_SHA512; # endif } # endif sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); sigdelset(&all_masked, SIGTRAP); sigdelset(&all_masked, SIGFPE); sigdelset(&all_masked, SIGBUS); sigdelset(&all_masked, SIGSEGV); memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); /* If we used getauxval, we already have all the values */ # ifndef OSSL_IMPLEMENT_GETAUXVAL if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_neon_probe(); OPENSSL_armcap_P |= ARMV7_NEON; if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_pmull_probe(); OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; } else if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_aes_probe(); OPENSSL_armcap_P |= ARMV8_AES; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha1_probe(); OPENSSL_armcap_P |= ARMV8_SHA1; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha256_probe(); OPENSSL_armcap_P |= ARMV8_SHA256; } # if defined(__aarch64__) && !defined(__APPLE__) if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha512_probe(); OPENSSL_armcap_P |= ARMV8_SHA512; } # endif } # endif /* Things that getauxval didn't tell us */ if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_tick(); OPENSSL_armcap_P |= ARMV7_TICK; } sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); }
unsigned long qemu_getauxval(unsigned long key) { return getauxval(key); }
void OPENSSL_cpuid_setup(void) { char *e; struct sigaction ill_oact, ill_act; sigset_t oset; static int trigger = 0; if (trigger) return; trigger = 1; if ((e = getenv("OPENSSL_ppccap"))) { OPENSSL_ppccap_P = strtoul(e, NULL, 0); return; } OPENSSL_ppccap_P = 0; #if defined(_AIX) OPENSSL_ppccap_P |= PPC_FPU; if (sizeof(size_t) == 4) { struct utsname uts; # if defined(_SC_AIX_KERNEL_BITMODE) if (sysconf(_SC_AIX_KERNEL_BITMODE) != 64) return; # endif if (uname(&uts) != 0 || atoi(uts.version) < 6) return; } # if defined(__power_set) /* * Value used in __power_set is a single-bit 1<<n one denoting * specific processor class. Incidentally 0xffffffff<<n can be * used to denote specific processor and its successors. */ if (sizeof(size_t) == 4) { /* In 32-bit case PPC_FPU64 is always fastest [if option] */ if (__power_set(0xffffffffU<<13)) /* POWER5 and later */ OPENSSL_ppccap_P |= PPC_FPU64; } else { /* In 64-bit case PPC_FPU64 is fastest only on POWER6 */ if (__power_set(0x1U<<14)) /* POWER6 */ OPENSSL_ppccap_P |= PPC_FPU64; } if (__power_set(0xffffffffU<<14)) /* POWER6 and later */ OPENSSL_ppccap_P |= PPC_ALTIVEC; if (__power_set(0xffffffffU<<16)) /* POWER8 and later */ OPENSSL_ppccap_P |= PPC_CRYPTO207; if (__power_set(0xffffffffU<<17)) /* POWER9 and later */ OPENSSL_ppccap_P |= PPC_MADD300; return; # endif #endif if (getauxval != NULL) { unsigned long hwcap = getauxval(HWCAP); if (hwcap & HWCAP_FPU) { OPENSSL_ppccap_P |= PPC_FPU; if (sizeof(size_t) == 4) { /* In 32-bit case PPC_FPU64 is always fastest [if option] */ if (hwcap & HWCAP_PPC64) OPENSSL_ppccap_P |= PPC_FPU64; } else { /* In 64-bit case PPC_FPU64 is fastest only on POWER6 */ if (hwcap & HWCAP_POWER6_EXT) OPENSSL_ppccap_P |= PPC_FPU64; } } if (hwcap & HWCAP_ALTIVEC) { OPENSSL_ppccap_P |= PPC_ALTIVEC; if ((hwcap & HWCAP_VSX) && (getauxval(HWCAP2) & HWCAP_VEC_CRYPTO)) OPENSSL_ppccap_P |= PPC_CRYPTO207; } if (hwcap & HWCAP_ARCH_3_00) { OPENSSL_ppccap_P |= PPC_MADD300; } return; } sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); sigdelset(&all_masked, SIGTRAP); #ifdef SIGEMT sigdelset(&all_masked, SIGEMT); #endif sigdelset(&all_masked, SIGFPE); sigdelset(&all_masked, SIGBUS); sigdelset(&all_masked, SIGSEGV); memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); if (sigsetjmp(ill_jmp,1) == 0) { OPENSSL_fpu_probe(); OPENSSL_ppccap_P |= PPC_FPU; if (sizeof(size_t) == 4) { #ifdef __linux struct utsname uts; if (uname(&uts) == 0 && strcmp(uts.machine, "ppc64") == 0) #endif if (sigsetjmp(ill_jmp, 1) == 0) { OPENSSL_ppc64_probe(); OPENSSL_ppccap_P |= PPC_FPU64; } } else { /* * Wanted code detecting POWER6 CPU and setting PPC_FPU64 */ } } if (sigsetjmp(ill_jmp, 1) == 0) { OPENSSL_altivec_probe(); OPENSSL_ppccap_P |= PPC_ALTIVEC; if (sigsetjmp(ill_jmp, 1) == 0) { OPENSSL_crypto207_probe(); OPENSSL_ppccap_P |= PPC_CRYPTO207; } } if (sigsetjmp(ill_jmp, 1) == 0) { OPENSSL_madd300_probe(); OPENSSL_ppccap_P |= PPC_MADD300; } sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); }
void GFp_cpuid_setup(void) { char *cpuinfo_data; size_t cpuinfo_len; if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) { return; } STRING_PIECE cpuinfo; cpuinfo.data = cpuinfo_data; cpuinfo.len = cpuinfo_len; /* |getauxval| is not available on Android until API level 20. If it is * unavailable, read from /proc/self/auxv as a fallback. This is unreadable * on some versions of Android, so further fall back to /proc/cpuinfo. * * See * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2 * and b/13679666 (Google-internal) for details. */ unsigned long hwcap = 0; if (getauxval != NULL) { hwcap = getauxval(AT_HWCAP); } if (hwcap == 0) { hwcap = getauxval_proc(AT_HWCAP); } if (hwcap == 0) { hwcap = get_hwcap_cpuinfo(&cpuinfo); } /* Clear NEON support if known broken. */ g_has_broken_neon = has_broken_neon(&cpuinfo); if (g_has_broken_neon) { hwcap &= ~HWCAP_NEON; } /* Matching OpenSSL, only report other features if NEON is present. */ if (hwcap & HWCAP_NEON) { GFp_armcap_P |= ARMV7_NEON; /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to * /proc/cpuinfo. See https://crbug.com/596156. */ unsigned long hwcap2 = 0; if (getauxval != NULL) { hwcap2 = getauxval(AT_HWCAP2); } if (hwcap2 == 0) { hwcap2 = get_hwcap2_cpuinfo(&cpuinfo); } if (hwcap2 & HWCAP2_AES) { GFp_armcap_P |= ARMV8_AES; } if (hwcap2 & HWCAP2_PMULL) { GFp_armcap_P |= ARMV8_PMULL; } if (hwcap2 & HWCAP2_SHA1) { GFp_armcap_P |= ARMV8_SHA1; } if (hwcap2 & HWCAP2_SHA2) { GFp_armcap_P |= ARMV8_SHA256; } } OPENSSL_free(cpuinfo_data); }
// Returns the address of the next page after address 'x', unless 'x' is // itself at the start of a page. #define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) extern "C" int __cxa_atexit(void (*)(void *), void *, void *); static void call_array(void(**list)()) { // First element is -1, list is null-terminated while (*++list) { (*list)(); } } static void apply_gnu_relro() { ElfW(Phdr)* phdr_start = reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)); unsigned long int phdr_ct = getauxval(AT_PHNUM); for (ElfW(Phdr)* phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) { if (phdr->p_type != PT_GNU_RELRO) { continue; } ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr); ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz); // Check return value here? What do we do if we fail? mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_end - seg_page_start, PROT_READ); } } __noreturn void __libc_init(void* raw_args,
void VM_Version::get_processor_features() { _supports_cx8 = true; _supports_atomic_getset4 = true; _supports_atomic_getadd4 = true; _supports_atomic_getset8 = true; _supports_atomic_getadd8 = true; if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize)) FLAG_SET_DEFAULT(AllocatePrefetchStepSize, 64); FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 256); FLAG_SET_DEFAULT(PrefetchFieldsAhead, 256); FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 256); FLAG_SET_DEFAULT(UseSSE42Intrinsics, true); unsigned long auxv = getauxval(AT_HWCAP); char buf[512]; _features = auxv; int cpu_lines = 0; if (FILE *f = fopen("/proc/cpuinfo", "r")) { char buf[128], *p; while (fgets(buf, sizeof (buf), f) != NULL) { if (p = strchr(buf, ':')) { long v = strtol(p+1, NULL, 0); if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) { _cpu = v; cpu_lines++; } else if (strncmp(buf, "CPU variant", sizeof "CPU variant" - 1) == 0) { _variant = v; } else if (strncmp(buf, "CPU part", sizeof "CPU part" - 1) == 0) { if (_model != v) _model2 = _model; _model = v; } else if (strncmp(buf, "CPU revision", sizeof "CPU revision" - 1) == 0) { _revision = v; } } } fclose(f); } // Enable vendor specific features if (_cpu == CPU_CAVIUM && _variant == 0) _features |= CPU_DMB_ATOMICS; if (_cpu == CPU_ARM && (_model == 0xd03 || _model2 == 0xd03)) _features |= CPU_A53MAC; // If an olde style /proc/cpuinfo (cpu_lines == 1) then if _model is an A57 (0xd07) // we assume the worst and assume we could be on a big little system and have // undisclosed A53 cores which we could be swapped to at any stage if (_cpu == CPU_ARM && cpu_lines == 1 && _model == 0xd07) _features |= CPU_A53MAC; sprintf(buf, "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); if (_model2) sprintf(buf+strlen(buf), "(0x%03x)", _model2); if (auxv & HWCAP_ASIMD) strcat(buf, ", simd"); if (auxv & HWCAP_CRC32) strcat(buf, ", crc"); if (auxv & HWCAP_AES) strcat(buf, ", aes"); if (auxv & HWCAP_SHA1) strcat(buf, ", sha1"); if (auxv & HWCAP_SHA2) strcat(buf, ", sha256"); _features_string = os::strdup(buf); if (FLAG_IS_DEFAULT(UseCRC32)) { UseCRC32 = (auxv & HWCAP_CRC32) != 0; } if (UseCRC32 && (auxv & HWCAP_CRC32) == 0) { warning("UseCRC32 specified, but not supported on this CPU"); } if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) { FLAG_SET_DEFAULT(UseAdler32Intrinsics, true); } if (UseVectorizedMismatchIntrinsic) { warning("UseVectorizedMismatchIntrinsic specified, but not available on this CPU."); FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false); } if (auxv & HWCAP_AES) { UseAES = UseAES || FLAG_IS_DEFAULT(UseAES); UseAESIntrinsics = UseAESIntrinsics || (UseAES && FLAG_IS_DEFAULT(UseAESIntrinsics)); if (UseAESIntrinsics && !UseAES) { warning("UseAESIntrinsics enabled, but UseAES not, enabling"); UseAES = true; } } else { if (UseAES) { warning("UseAES specified, but not supported on this CPU"); } if (UseAESIntrinsics) { warning("UseAESIntrinsics specified, but not supported on this CPU"); } } if (UseAESCTRIntrinsics) { warning("AES/CTR intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); } if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { UseCRC32Intrinsics = true; } if (auxv & HWCAP_CRC32) { if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); } } else if (UseCRC32CIntrinsics) { warning("CRC32C is not available on the CPU"); FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); } if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) { if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); } } else if (UseSHA) { warning("SHA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA, false); } if (UseSHA && (auxv & HWCAP_SHA1)) { if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); } } else if (UseSHA1Intrinsics) { warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); } if (UseSHA && (auxv & HWCAP_SHA2)) { if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); } } else if (UseSHA256Intrinsics) { warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); } if (UseSHA512Intrinsics) { warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { FLAG_SET_DEFAULT(UseSHA, false); } if (auxv & HWCAP_PMULL) { if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) { FLAG_SET_DEFAULT(UseGHASHIntrinsics, true); } } else if (UseGHASHIntrinsics) { warning("GHASH intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } // This machine allows unaligned memory accesses if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { FLAG_SET_DEFAULT(UseUnalignedAccesses, true); } if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } if (FLAG_IS_DEFAULT(UseBarriersForVolatile)) { UseBarriersForVolatile = (_features & CPU_DMB_ATOMICS) != 0; } if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { UsePopCountInstruction = true; } if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { UseMontgomeryMultiplyIntrinsic = true; } if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { UseMontgomerySquareIntrinsic = true; } #ifdef COMPILER2 if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; } #endif }
static int getentropy_fallback(void *buf, size_t len) { uint8_t results[SHA512_DIGEST_LENGTH]; int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; static int cnt; struct timespec ts; struct timeval tv; struct rusage ru; sigset_t sigset; struct stat st; SHA512_CTX ctx; static pid_t lastpid; pid_t pid; size_t i, ii, m; char *p; pid = getpid(); if (lastpid == pid) { faster = 1; repeat = 2; } else { faster = 0; lastpid = pid; repeat = REPEAT; } for (i = 0; i < len; ) { int j; SHA512_Init(&ctx); for (j = 0; j < repeat; j++) { HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } dl_iterate_phdr(getentropy_phdr, &ctx); for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) HX(clock_gettime(cl[ii], &ts) == -1, ts); HX((pid = getpid()) == -1, pid); HX((pid = getsid(pid)) == -1, pid); HX((pid = getppid()) == -1, pid); HX((pid = getpgid(0)) == -1, pid); HX((e = getpriority(0, 0)) == -1, e); if (!faster) { ts.tv_sec = 0; ts.tv_nsec = 1; (void) nanosleep(&ts, NULL); } HX(sigpending(&sigset) == -1, sigset); HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, sigset); HF(getentropy); /* an addr in this library */ HF(printf); /* an addr in libc */ p = (char *)&p; HD(p); /* an addr on stack */ p = (char *)&errno; HD(p); /* the addr of errno */ if (i == 0) { struct sockaddr_storage ss; struct statvfs stvfs; struct termios tios; struct statfs stfs; socklen_t ssl; off_t off; /* * Prime-sized mappings encourage fragmentation; * thus exposing some address entropy. */ struct mm { size_t npg; void *p; } mm[] = { { 17, MAP_FAILED }, { 3, MAP_FAILED }, { 11, MAP_FAILED }, { 2, MAP_FAILED }, { 5, MAP_FAILED }, { 3, MAP_FAILED }, { 7, MAP_FAILED }, { 1, MAP_FAILED }, { 57, MAP_FAILED }, { 3, MAP_FAILED }, { 131, MAP_FAILED }, { 1, MAP_FAILED }, }; for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { HX(mm[m].p = mmap(NULL, mm[m].npg * pgs, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0), mm[m].p); if (mm[m].p != MAP_FAILED) { size_t mo; /* Touch some memory... */ p = mm[m].p; mo = cnt % (mm[m].npg * pgs - 1); p[mo] = 1; cnt += (int)((long)(mm[m].p) / pgs); } /* Check cnts and times... */ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) { HX((e = clock_gettime(cl[ii], &ts)) == -1, ts); if (e != -1) cnt += (int)ts.tv_nsec; } HX((e = getrusage(RUSAGE_SELF, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { if (mm[m].p != MAP_FAILED) munmap(mm[m].p, mm[m].npg * pgs); mm[m].p = MAP_FAILED; } HX(stat(".", &st) == -1, st); HX(statvfs(".", &stvfs) == -1, stvfs); HX(statfs(".", &stfs) == -1, stfs); HX(stat("/", &st) == -1, st); HX(statvfs("/", &stvfs) == -1, stvfs); HX(statfs("/", &stfs) == -1, stfs); HX((e = fstat(0, &st)) == -1, st); if (e == -1) { if (S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { HX(fstatvfs(0, &stvfs) == -1, stvfs); HX(fstatfs(0, &stfs) == -1, stfs); HX((off = lseek(0, (off_t)0, SEEK_CUR)) < 0, off); } if (S_ISCHR(st.st_mode)) { HX(tcgetattr(0, &tios) == -1, tios); } else if (S_ISSOCK(st.st_mode)) { memset(&ss, 0, sizeof ss); ssl = sizeof(ss); HX(getpeername(0, (void *)&ss, &ssl) == -1, ss); } } HX((e = getrusage(RUSAGE_CHILDREN, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } else { /* Subsequent hashes absorb previous result */ HD(results); } HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } HD(cnt); } #ifdef HAVE_GETAUXVAL #ifdef AT_RANDOM /* Not as random as you think but we take what we are given */ p = (char *) getauxval(AT_RANDOM); if (p) HR(p, 16); #endif #ifdef AT_SYSINFO_EHDR p = (char *) getauxval(AT_SYSINFO_EHDR); if (p) HR(p, pgs); #endif #ifdef AT_BASE p = (char *) getauxval(AT_BASE); if (p) HD(p); #endif #endif SHA512_Final(results, &ctx); memcpy((char *)buf + i, results, min(sizeof(results), len - i)); i += min(sizeof(results), len - i); } explicit_bzero(&ctx, sizeof ctx); explicit_bzero(results, sizeof results); if (gotdata(buf, len) == 0) { errno = save_errno; return (0); /* satisfied */ } errno = EIO; return (-1); }
int main() { // Did getauxval during preinit get the same results as getauxval now? CHECK(getauxval(AT_RANDOM) == g_AT_RANDOM); CHECK(getauxval(AT_PAGESZ) == g_AT_PAGESZ); return 0; }
static void preinit_ctor() { g_AT_RANDOM = getauxval(AT_RANDOM); g_AT_PAGESZ = getauxval(AT_PAGESZ); }
void mono_hwcap_arch_init (void) { #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID) unsigned long hwcap; unsigned long platform; if ((hwcap = getauxval(AT_HWCAP))) { /* HWCAP_ARM_THUMB */ if (hwcap & 0x00000004) mono_hwcap_arm_has_thumb = TRUE; /* HWCAP_ARM_VFP */ if (hwcap & 0x00000064) mono_hwcap_arm_has_vfp = TRUE; /* TODO: Find a way to detect Thumb 2. */ } if ((platform = getauxval(AT_PLATFORM))) { const char *str = (const char *) platform; if (str [1] >= '5') mono_hwcap_arm_is_v5 = TRUE; if (str [1] >= '6') mono_hwcap_arm_is_v6 = TRUE; if (str [1] >= '7') mono_hwcap_arm_is_v7 = TRUE; /* TODO: Find a way to detect v7s. */ } #elif defined(__APPLE__) cpu_subtype_t sub_type; size_t length = sizeof (sub_type); sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0); if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) { mono_hwcap_arm_is_v5 = TRUE; } else if (sub_type == CPU_SUBTYPE_ARM_V6) { mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) { mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; mono_hwcap_arm_is_v7 = TRUE; } /* TODO: Find a way to detect features like Thumb and VFP. */ #else /* We can't use the auxiliary vector on Android due to * permissions, so fall back to /proc/cpuinfo. We also * hit this path if the target doesn't have sys/auxv.h. */ char buf [512]; char *line; FILE *file = fopen ("/proc/cpuinfo", "r"); if (file) { while ((line = fgets (buf, 512, file))) { if (!strncmp (line, "Processor", 9)) { char *ver = strstr (line, "(v"); if (ver) { if (ver [2] >= '5') mono_hwcap_arm_is_v5 = TRUE; if (ver [2] >= '6') mono_hwcap_arm_is_v6 = TRUE; if (ver [2] >= '7') mono_hwcap_arm_is_v7 = TRUE; /* TODO: Find a way to detect v7s. */ } continue; } if (!strncmp (line, "Features", 8)) { if (strstr (line, "thumb")) mono_hwcap_arm_has_thumb = TRUE; /* TODO: Find a way to detect Thumb 2. */ if (strstr (line, "vfp")) mono_hwcap_arm_has_vfp = TRUE; continue; } } fclose (file); } #endif }
TEST(getauxval, unexpected_values) { ASSERT_EQ((unsigned long int) 0, getauxval(0xdeadbeef)); }
void mono_hwcap_arch_init (void) { #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID) unsigned long hwcap; unsigned long platform; if ((hwcap = getauxval(AT_HWCAP))) { /* HWCAP_ARM_THUMB */ if (hwcap & 0x00000004) mono_hwcap_arm_has_thumb = TRUE; /* HWCAP_ARM_VFP */ if (hwcap & 0x00000040) mono_hwcap_arm_has_vfp = TRUE; /* HWCAP_ARM_VFPv3 */ if (hwcap & 0x00002000) mono_hwcap_arm_has_vfp3 = TRUE; /* HWCAP_ARM_VFPv3D16 */ if (hwcap & 0x00004000) mono_hwcap_arm_has_vfp3_d16 = TRUE; /* TODO: Find a way to detect Thumb 2. */ } if ((platform = getauxval(AT_PLATFORM))) { const char *str = (const char *) platform; if (str [1] >= '5') mono_hwcap_arm_is_v5 = TRUE; if (str [1] >= '6') mono_hwcap_arm_is_v6 = TRUE; if (str [1] >= '7') mono_hwcap_arm_is_v7 = TRUE; /* TODO: Find a way to detect v7s. */ } #elif defined(__APPLE__) cpu_subtype_t sub_type; size_t length = sizeof (sub_type); sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0); if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) { mono_hwcap_arm_is_v5 = TRUE; } else if (sub_type == CPU_SUBTYPE_ARM_V6) { mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) { mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; mono_hwcap_arm_is_v7 = TRUE; } /* TODO: Find a way to detect features like Thumb and VFP. */ #else /* We can't use the auxiliary vector on Android due to * permissions, so fall back to /proc/cpuinfo. We also * hit this path if the target doesn't have sys/auxv.h. */ #if defined (HAVE_SYS_UTSNAME_H) struct utsname name; /* Only fails if `name` is invalid (it isn't). */ g_assert (!uname (&name)); if (!strncmp (name.machine, "aarch64", 7) || !strncmp (name.machine, "armv8", 5)) { /* * We're a 32-bit program running on an ARMv8 system. * Whether the system is actually 32-bit or 64-bit * doesn't matter to us. The important thing is that * all 3 of ARMv8's execution states (A64, A32, T32) * are guaranteed to have all of the features that * we want to detect and use. * * We do this ARMv8 detection via uname () because * in the early days of ARMv8 on Linux, the * /proc/cpuinfo format was a disaster and there * were multiple (merged into mainline) attempts at * cleaning it up (read: breaking applications that * tried to rely on it). So now multiple ARMv8 * systems in the wild have different /proc/cpuinfo * output, some of which are downright useless. * * So, when it comes to detecting ARMv8 in a 32-bit * program, it's better to just avoid /proc/cpuinfo * entirely. Maybe in a decade or two, we won't * have to worry about this mess that the Linux ARM * maintainers created. One can hope. */ mono_hwcap_arm_is_v5 = TRUE; mono_hwcap_arm_is_v6 = TRUE; mono_hwcap_arm_is_v7 = TRUE; mono_hwcap_arm_has_vfp = TRUE; mono_hwcap_arm_has_vfp3 = TRUE; mono_hwcap_arm_has_vfp3_d16 = TRUE; mono_hwcap_arm_has_thumb = TRUE; mono_hwcap_arm_has_thumb2 = TRUE; } #endif char buf [512]; char *line; FILE *file = fopen ("/proc/cpuinfo", "r"); if (file) { while ((line = fgets (buf, 512, file))) { if (!strncmp (line, "Processor", 9)) { char *ver = strstr (line, "(v"); if (ver) { if (ver [2] >= '5') mono_hwcap_arm_is_v5 = TRUE; if (ver [2] >= '6') mono_hwcap_arm_is_v6 = TRUE; if (ver [2] >= '7') mono_hwcap_arm_is_v7 = TRUE; /* TODO: Find a way to detect v7s. */ } continue; } if (!strncmp (line, "Features", 8)) { if (strstr (line, "thumb")) mono_hwcap_arm_has_thumb = TRUE; /* TODO: Find a way to detect Thumb 2. */ if (strstr (line, "vfp")) mono_hwcap_arm_has_vfp = TRUE; if (strstr (line, "vfpv3")) mono_hwcap_arm_has_vfp3 = TRUE; if (strstr (line, "vfpv3-d16")) mono_hwcap_arm_has_vfp3_d16 = TRUE; continue; } } fclose (file); } #endif }