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