diff options
author | Mykola Hohsadze <koliagogsadze@gmail.com> | 2023-09-19 12:02:25 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-19 11:02:25 +0200 |
commit | 89a3f0358a32268d1870a2e35e2a13b49ab7f126 (patch) | |
tree | 59669536b3d9c642c11d719f9ad2834e448965e9 /src/hwcaps.c | |
parent | 494d9657ef0435cd267ca0ed55c2d726704da9a4 (diff) | |
download | cpu_features-89a3f0358a32268d1870a2e35e2a13b49ab7f126.tar.gz |
Add FreeBSD Arm64 support (#295)
* Add FreeBSD Arm64 detection
Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c
* Add FreeBSD Arm64 tests
* Add flagm, flagm2 and rng detection
* Add HWCAP FreeBSD AArch64
* Update include to use linux hwcaps for powerpc
* Add FreeBSD aarch64 impl
* Separate Hwacps to freebsd and linux implementation
* Add aarch64 midr_el1 implementation
* Add detection hwcap cpuid to hwcaps.h
* Add MIDR_EL1 tests
Diffstat (limited to 'src/hwcaps.c')
-rw-r--r-- | src/hwcaps.c | 143 |
1 files changed, 1 insertions, 142 deletions
diff --git a/src/hwcaps.c b/src/hwcaps.c index f44f6c3..6e2e9a8 100644 --- a/src/hwcaps.c +++ b/src/hwcaps.c @@ -14,12 +14,7 @@ #include "internal/hwcaps.h" -#include <stdlib.h> -#include <string.h> - -#include "cpu_features_macros.h" -#include "internal/filesystem.h" -#include "internal/string_view.h" +#include <stdbool.h> static bool IsSet(const uint32_t mask, const uint32_t value) { if (mask == 0) return false; @@ -31,139 +26,3 @@ bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) || IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2); } - -#ifdef CPU_FEATURES_TEST -// In test mode, hwcaps_for_testing will define the following functions. -HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); -const char* CpuFeatures_GetPlatformPointer(void); -const char* CpuFeatures_GetBasePlatformPointer(void); -#else - -// Debug facilities -#if defined(NDEBUG) -#define D(...) -#else -#include <stdio.h> -#define D(...) \ - do { \ - printf(__VA_ARGS__); \ - fflush(stdout); \ - } while (0) -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Implementation of GetElfHwcapFromGetauxval -//////////////////////////////////////////////////////////////////////////////// - -#define AT_HWCAP 16 -#define AT_HWCAP2 26 -#define AT_PLATFORM 15 -#define AT_BASE_PLATFORM 24 - -#if defined(HAVE_STRONG_GETAUXVAL) -#include <sys/auxv.h> -static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { - return getauxval(hwcap_type); -} -#elif defined(HAVE_DLFCN_H) -// On Android we probe the system's C library for a 'getauxval' function and -// call it if it exits, or return 0 for failure. This function is available -// since API level 18. -// -// Note that getauxval() can't really be re-implemented here, because its -// implementation does not parse /proc/self/auxv. Instead it depends on values -// that are passed by the kernel at process-init time to the C runtime -// initialization layer. - -#include <dlfcn.h> - -typedef unsigned long getauxval_func_t(unsigned long); - -static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) { - uint32_t ret = 0; - void *libc_handle = NULL; - getauxval_func_t *func = NULL; - - dlerror(); // Cleaning error state before calling dlopen. - libc_handle = dlopen("libc.so", RTLD_NOW); - if (!libc_handle) { - D("Could not dlopen() C library: %s\n", dlerror()); - return 0; - } - func = (getauxval_func_t *)dlsym(libc_handle, "getauxval"); - if (!func) { - D("Could not find getauxval() in C library\n"); - } else { - // Note: getauxval() returns 0 on failure. Doesn't touch errno. - ret = (uint32_t)(*func)(hwcap_type); - } - dlclose(libc_handle); - return ret; -} -#else -#error "This platform does not provide hardware capabilities." -#endif - -// Implementation of GetHardwareCapabilities for OS that provide -// GetElfHwcapFromGetauxval(). - -// Fallback when getauxval is not available, retrieves hwcaps from -// "/proc/self/auxv". -static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) { - struct { - uint32_t tag; - uint32_t value; - } entry; - uint32_t result = 0; - const char filepath[] = "/proc/self/auxv"; - const int fd = CpuFeatures_OpenFile(filepath); - if (fd < 0) { - D("Could not open %s\n", filepath); - return 0; - } - for (;;) { - const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry); - if (ret < 0) { - D("Error while reading %s\n", filepath); - break; - } - // Detect end of list. - if (ret == 0 || (entry.tag == 0 && entry.value == 0)) { - break; - } - if (entry.tag == hwcap_type) { - result = entry.value; - break; - } - } - CpuFeatures_CloseFile(fd); - return result; -} - -// Retrieves hardware capabilities by first trying to call getauxval, if not -// available falls back to reading "/proc/self/auxv". -static unsigned long GetHardwareCapabilitiesFor(uint32_t type) { - unsigned long hwcaps = GetElfHwcapFromGetauxval(type); - if (!hwcaps) { - D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); - hwcaps = GetElfHwcapFromProcSelfAuxv(type); - } - return hwcaps; -} - -HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { - HardwareCapabilities capabilities; - capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP); - capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2); - return capabilities; -} - -const char *CpuFeatures_GetPlatformPointer(void) { - return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM); -} - -const char *CpuFeatures_GetBasePlatformPointer(void) { - return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); -} - -#endif // CPU_FEATURES_TEST |