xref: /dpdk/lib/eal/linux/eal_cpuflags.c (revision 30a1de105a5f40d77b344a891c4a68f79e815c43)
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
getauxval(unsigned long type __rte_unused)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
_rte_cpu_getauxval(unsigned long type,const char * str)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
rte_cpu_getauxval(unsigned long type)73 rte_cpu_getauxval(unsigned long type)
74 {
75 	return _rte_cpu_getauxval(type, NULL);
76 }
77 
78 int
rte_cpu_strcmp_auxval(unsigned long type,const char * str)79 rte_cpu_strcmp_auxval(unsigned long type, const char *str)
80 {
81 	return _rte_cpu_getauxval(type, str);
82 }
83