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