1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018 Red Hat, Inc. 3 */ 4 5 #include <elf.h> 6 #include <fcntl.h> 7 #include <string.h> 8 #include <sys/stat.h> 9 #include <sys/types.h> 10 #include <unistd.h> 11 12 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) 13 #if __GLIBC_PREREQ(2, 16) 14 #include <sys/auxv.h> 15 #define HAS_AUXV 1 16 #endif 17 #endif 18 19 #include <rte_cpuflags.h> 20 21 #ifndef HAS_AUXV 22 static unsigned long 23 getauxval(unsigned long type __rte_unused) 24 { 25 errno = ENOTSUP; 26 return 0; 27 } 28 #endif 29 30 #ifdef RTE_ARCH_64 31 typedef Elf64_auxv_t Internal_Elfx_auxv_t; 32 #else 33 typedef Elf32_auxv_t Internal_Elfx_auxv_t; 34 #endif 35 36 /** 37 * Provides a method for retrieving values from the auxiliary vector and 38 * possibly running a string comparison. 39 * 40 * @return Always returns a result. When the result is 0, check errno 41 * to see if an error occurred during processing. 42 */ 43 static unsigned long 44 _rte_cpu_getauxval(unsigned long type, const char *str) 45 { 46 unsigned long val; 47 48 errno = 0; 49 val = getauxval(type); 50 51 if (!val && (errno == ENOTSUP || errno == ENOENT)) { 52 int auxv_fd = open("/proc/self/auxv", O_RDONLY); 53 Internal_Elfx_auxv_t auxv; 54 55 if (auxv_fd == -1) 56 return 0; 57 58 errno = ENOENT; 59 while (read(auxv_fd, &auxv, sizeof(auxv)) == sizeof(auxv)) { 60 if (auxv.a_type == type) { 61 errno = 0; 62 val = auxv.a_un.a_val; 63 if (str) 64 val = strcmp((const char *)val, str); 65 break; 66 } 67 } 68 close(auxv_fd); 69 } 70 71 return val; 72 } 73 74 unsigned long 75 rte_cpu_getauxval(unsigned long type) 76 { 77 return _rte_cpu_getauxval(type, NULL); 78 } 79 80 int 81 rte_cpu_strcmp_auxval(unsigned long type, const char *str) 82 { 83 return _rte_cpu_getauxval(type, str); 84 } 85