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