4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2015, Joyent, Inc.
30 * String conversion routine for hardware capabilities types.
35 #include <sys/machelf.h>
37 #include <sys/auxv_SPARC.h>
38 #include <sys/auxv_386.h>
42 * Given a literal string, generate an initialization for an
45 #define STRDESC(_str) { _str, sizeof (_str) - 1 }
48 * The items in the elfcap_desc_t arrays are required to be
49 * ordered so that the array index is related to the
52 * array[ndx].c_val = 2^ndx
56 * array[0].c_val = 2^0 = 1
57 * array[1].c_val = 2^1 = 2
58 * array[2].c_val = 2^2 = 4
63 * Since 0 is not a valid value for the c_val field, we use it to
64 * mark an array entry that is a placeholder. This can happen if there
65 * is a hole in the assigned bits.
67 * The RESERVED_ELFCAP_DESC macro is used to reserve such holes.
69 #define RESERVED_ELFCAP_DESC { 0, { NULL, 0 }, { NULL, 0 }, { NULL, 0 } }
72 * Define separators for output string processing. This must be kept in
73 * sync with the elfcap_fmt_t values in elfcap.h.
75 static const elfcap_str_t format
[] = {
76 STRDESC(" "), /* ELFCAP_FMT_SNGSPACE */
77 STRDESC(" "), /* ELFCAP_FMT_DBLSPACE */
78 STRDESC(" | ") /* ELFCAP_FMT_PIPSPACE */
80 #define FORMAT_NELTS (sizeof (format) / sizeof (format[0]))
85 * Define all known software capabilities in all the supported styles.
86 * Order the capabilities by their numeric value. See SF1_SUNW_
87 * values in sys/elf.h.
89 static const elfcap_desc_t sf1
[ELFCAP_NUM_SF1
] = {
91 SF1_SUNW_FPKNWN
, STRDESC("SF1_SUNW_FPKNWN"),
92 STRDESC("FPKNWN"), STRDESC("fpknwn")
95 SF1_SUNW_FPUSED
, STRDESC("SF1_SUNW_FPUSED"),
96 STRDESC("FPUSED"), STRDESC("fpused"),
99 SF1_SUNW_ADDR32
, STRDESC("SF1_SUNW_ADDR32"),
100 STRDESC("ADDR32"), STRDESC("addr32"),
107 * Order the SPARC hardware capabilities to match their numeric value. See
108 * AV_SPARC_ values in sys/auxv_SPARC.h.
110 static const elfcap_desc_t hw1_sparc
[ELFCAP_NUM_HW1_SPARC
] = {
112 AV_SPARC_MUL32
, STRDESC("AV_SPARC_MUL32"),
113 STRDESC("MUL32"), STRDESC("mul32"),
116 AV_SPARC_DIV32
, STRDESC("AV_SPARC_DIV32"),
117 STRDESC("DIV32"), STRDESC("div32"),
120 AV_SPARC_FSMULD
, STRDESC("AV_SPARC_FSMULD"),
121 STRDESC("FSMULD"), STRDESC("fsmuld"),
124 AV_SPARC_V8PLUS
, STRDESC("AV_SPARC_V8PLUS"),
125 STRDESC("V8PLUS"), STRDESC("v8plus"),
128 AV_SPARC_POPC
, STRDESC("AV_SPARC_POPC"),
129 STRDESC("POPC"), STRDESC("popc"),
132 AV_SPARC_VIS
, STRDESC("AV_SPARC_VIS"),
133 STRDESC("VIS"), STRDESC("vis"),
136 AV_SPARC_VIS2
, STRDESC("AV_SPARC_VIS2"),
137 STRDESC("VIS2"), STRDESC("vis2"),
140 AV_SPARC_ASI_BLK_INIT
, STRDESC("AV_SPARC_ASI_BLK_INIT"),
141 STRDESC("ASI_BLK_INIT"), STRDESC("asi_blk_init"),
144 AV_SPARC_FMAF
, STRDESC("AV_SPARC_FMAF"),
145 STRDESC("FMAF"), STRDESC("fmaf"),
147 RESERVED_ELFCAP_DESC
, /* 0x00000200 */
149 AV_SPARC_VIS3
, STRDESC("AV_SPARC_VIS3"),
150 STRDESC("VIS3"), STRDESC("vis3"),
153 AV_SPARC_HPC
, STRDESC("AV_SPARC_HPC"),
154 STRDESC("HPC"), STRDESC("hpc"),
157 AV_SPARC_RANDOM
, STRDESC("AV_SPARC_RANDOM"),
158 STRDESC("RANDOM"), STRDESC("random"),
161 AV_SPARC_TRANS
, STRDESC("AV_SPARC_TRANS"),
162 STRDESC("TRANS"), STRDESC("trans"),
165 AV_SPARC_FJFMAU
, STRDESC("AV_SPARC_FJFMAU"),
166 STRDESC("FJFMAU"), STRDESC("fjfmau"),
169 AV_SPARC_IMA
, STRDESC("AV_SPARC_IMA"),
170 STRDESC("IMA"), STRDESC("ima"),
173 AV_SPARC_ASI_CACHE_SPARING
,
174 STRDESC("AV_SPARC_ASI_CACHE_SPARING"),
175 STRDESC("CSPARE"), STRDESC("cspare"),
182 * Order the Intel hardware capabilities to match their numeric value. See
183 * AV_386_ values in sys/auxv_386.h.
185 static const elfcap_desc_t hw1_386
[ELFCAP_NUM_HW1_386
] = {
187 AV_386_FPU
, STRDESC("AV_386_FPU"),
188 STRDESC("FPU"), STRDESC("fpu"),
191 AV_386_TSC
, STRDESC("AV_386_TSC"),
192 STRDESC("TSC"), STRDESC("tsc"),
195 AV_386_CX8
, STRDESC("AV_386_CX8"),
196 STRDESC("CX8"), STRDESC("cx8"),
199 AV_386_SEP
, STRDESC("AV_386_SEP"),
200 STRDESC("SEP"), STRDESC("sep"),
203 AV_386_AMD_SYSC
, STRDESC("AV_386_AMD_SYSC"),
204 STRDESC("AMD_SYSC"), STRDESC("amd_sysc"),
207 AV_386_CMOV
, STRDESC("AV_386_CMOV"),
208 STRDESC("CMOV"), STRDESC("cmov"),
211 AV_386_MMX
, STRDESC("AV_386_MMX"),
212 STRDESC("MMX"), STRDESC("mmx"),
215 AV_386_AMD_MMX
, STRDESC("AV_386_AMD_MMX"),
216 STRDESC("AMD_MMX"), STRDESC("amd_mmx"),
219 AV_386_AMD_3DNow
, STRDESC("AV_386_AMD_3DNow"),
220 STRDESC("AMD_3DNow"), STRDESC("amd_3dnow"),
223 AV_386_AMD_3DNowx
, STRDESC("AV_386_AMD_3DNowx"),
224 STRDESC("AMD_3DNowx"), STRDESC("amd_3dnowx"),
227 AV_386_FXSR
, STRDESC("AV_386_FXSR"),
228 STRDESC("FXSR"), STRDESC("fxsr"),
231 AV_386_SSE
, STRDESC("AV_386_SSE"),
232 STRDESC("SSE"), STRDESC("sse"),
235 AV_386_SSE2
, STRDESC("AV_386_SSE2"),
236 STRDESC("SSE2"), STRDESC("sse2"),
238 /* 0x02000 withdrawn - do not assign */
240 AV_386_SSE3
, STRDESC("AV_386_SSE3"),
241 STRDESC("SSE3"), STRDESC("sse3"),
243 /* 0x08000 withdrawn - do not assign */
245 AV_386_CX16
, STRDESC("AV_386_CX16"),
246 STRDESC("CX16"), STRDESC("cx16"),
249 AV_386_AHF
, STRDESC("AV_386_AHF"),
250 STRDESC("AHF"), STRDESC("ahf"),
253 AV_386_TSCP
, STRDESC("AV_386_TSCP"),
254 STRDESC("TSCP"), STRDESC("tscp"),
257 AV_386_AMD_SSE4A
, STRDESC("AV_386_AMD_SSE4A"),
258 STRDESC("AMD_SSE4A"), STRDESC("amd_sse4a"),
261 AV_386_POPCNT
, STRDESC("AV_386_POPCNT"),
262 STRDESC("POPCNT"), STRDESC("popcnt"),
265 AV_386_AMD_LZCNT
, STRDESC("AV_386_AMD_LZCNT"),
266 STRDESC("AMD_LZCNT"), STRDESC("amd_lzcnt"),
269 AV_386_SSSE3
, STRDESC("AV_386_SSSE3"),
270 STRDESC("SSSE3"), STRDESC("ssse3"),
273 AV_386_SSE4_1
, STRDESC("AV_386_SSE4_1"),
274 STRDESC("SSE4.1"), STRDESC("sse4.1"),
277 AV_386_SSE4_2
, STRDESC("AV_386_SSE4_2"),
278 STRDESC("SSE4.2"), STRDESC("sse4.2"),
281 AV_386_MOVBE
, STRDESC("AV_386_MOVBE"),
282 STRDESC("MOVBE"), STRDESC("movbe"),
285 AV_386_AES
, STRDESC("AV_386_AES"),
286 STRDESC("AES"), STRDESC("aes"),
289 AV_386_PCLMULQDQ
, STRDESC("AV_386_PCLMULQDQ"),
290 STRDESC("PCLMULQDQ"), STRDESC("pclmulqdq"),
293 AV_386_XSAVE
, STRDESC("AV_386_XSAVE"),
294 STRDESC("XSAVE"), STRDESC("xsave"),
297 AV_386_AVX
, STRDESC("AV_386_AVX"),
298 STRDESC("AVX"), STRDESC("avx"),
301 AV_386_VMX
, STRDESC("AV_386_VMX"),
302 STRDESC("VMX"), STRDESC("vmx"),
305 AV_386_AMD_SVM
, STRDESC("AV_386_AMD_SVM"),
306 STRDESC("AMD_SVM"), STRDESC("amd_svm"),
310 static const elfcap_desc_t hw2_386
[ELFCAP_NUM_HW2_386
] = {
312 AV_386_2_F16C
, STRDESC("AV_386_2_F16C"),
313 STRDESC("F16C"), STRDESC("f16c"),
316 AV_386_2_RDRAND
, STRDESC("AV_386_2_RDRAND"),
317 STRDESC("RDRAND"), STRDESC("rdrand"),
320 AV_386_2_BMI1
, STRDESC("AV_386_2_BMI1"),
321 STRDESC("BMI1"), STRDESC("bmi1"),
324 AV_386_2_BMI2
, STRDESC("AV_386_2_BMI2"),
325 STRDESC("BMI2"), STRDESC("bmi2"),
328 AV_386_2_FMA
, STRDESC("AV_386_2_FMA"),
329 STRDESC("FMA"), STRDESC("fma"),
332 AV_386_2_AVX2
, STRDESC("AV_386_2_AVX2"),
333 STRDESC("AVX2"), STRDESC("avx2"),
336 AV_386_2_ADX
, STRDESC("AV_386_2_ADX"),
337 STRDESC("ADX"), STRDESC("adx"),
340 AV_386_2_RDSEED
, STRDESC("AV_386_2_RDSEED"),
341 STRDESC("RDSEED"), STRDESC("rdseed"),
346 * Concatenate a token to the string buffer. This can be a capabilities token
347 * or a separator token.
350 token(char **ostr
, size_t *olen
, const elfcap_str_t
*nstr
)
352 if (*olen
< nstr
->s_len
)
353 return (ELFCAP_ERR_BUFOVFL
);
355 (void) strcat(*ostr
, nstr
->s_str
);
356 *ostr
+= nstr
->s_len
;
357 *olen
-= nstr
->s_len
;
359 return (ELFCAP_ERR_NONE
);
363 get_str_desc(elfcap_style_t style
, const elfcap_desc_t
*cdp
,
364 const elfcap_str_t
**ret_str
)
366 switch (ELFCAP_STYLE_MASK(style
)) {
367 case ELFCAP_STYLE_FULL
:
368 *ret_str
= &cdp
->c_full
;
370 case ELFCAP_STYLE_UC
:
371 *ret_str
= &cdp
->c_uc
;
373 case ELFCAP_STYLE_LC
:
374 *ret_str
= &cdp
->c_lc
;
377 return (ELFCAP_ERR_INVSTYLE
);
380 return (ELFCAP_ERR_NONE
);
385 * Expand a capabilities value into the strings defined in the associated
386 * capabilities descriptor.
389 expand(elfcap_style_t style
, elfcap_mask_t val
, const elfcap_desc_t
*cdp
,
390 uint_t cnum
, char *str
, size_t slen
, elfcap_fmt_t fmt
)
394 const elfcap_str_t
*nstr
;
397 return (ELFCAP_ERR_NONE
);
399 for (cnt
= cnum
; cnt
> 0; cnt
--) {
400 uint_t mask
= cdp
[cnt
- 1].c_val
;
402 if ((val
& mask
) != 0) {
403 if (follow
++ && ((err
= token(&str
, &slen
,
404 &format
[fmt
])) != ELFCAP_ERR_NONE
))
407 err
= get_str_desc(style
, &cdp
[cnt
- 1], &nstr
);
408 if (err
!= ELFCAP_ERR_NONE
)
410 if ((err
= token(&str
, &slen
, nstr
)) != ELFCAP_ERR_NONE
)
418 * If there are any unknown bits remaining display the numeric value.
421 if (follow
&& ((err
= token(&str
, &slen
, &format
[fmt
])) !=
425 (void) snprintf(str
, slen
, "0x%x", val
);
427 return (ELFCAP_ERR_NONE
);
431 * Expand a CA_SUNW_HW_1 value.
434 elfcap_hw1_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
435 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
438 * Initialize the string buffer, and validate the format request.
441 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
442 return (ELFCAP_ERR_INVFMT
);
444 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
445 return (expand(style
, val
, &hw1_386
[0], ELFCAP_NUM_HW1_386
,
448 if ((mach
== EM_SPARC
) || (mach
== EM_SPARC32PLUS
) ||
449 (mach
== EM_SPARCV9
))
450 return (expand(style
, val
, hw1_sparc
, ELFCAP_NUM_HW1_SPARC
,
453 return (ELFCAP_ERR_UNKMACH
);
457 * Expand a CA_SUNW_HW_2 value.
460 elfcap_hw2_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
461 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
464 * Initialize the string buffer, and validate the format request.
467 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
468 return (ELFCAP_ERR_INVFMT
);
470 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
471 return (expand(style
, val
, &hw2_386
[0], ELFCAP_NUM_HW2_386
,
474 return (expand(style
, val
, NULL
, 0, str
, len
, fmt
));
478 * Expand a CA_SUNW_SF_1 value. Note, that at present these capabilities are
479 * common across all platforms. The use of "mach" is therefore redundant, but
480 * is retained for compatibility with the interface of elfcap_hw1_to_str(), and
481 * possible future expansion.
485 elfcap_sf1_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
486 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
489 * Initialize the string buffer, and validate the format request.
492 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
493 return (ELFCAP_ERR_INVFMT
);
495 return (expand(style
, val
, &sf1
[0], ELFCAP_NUM_SF1
, str
, len
, fmt
));
499 * Given a capability tag type and value, map it to a string representation.
502 elfcap_tag_to_str(elfcap_style_t style
, uint64_t tag
, elfcap_mask_t val
,
503 char *str
, size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
507 return (elfcap_hw1_to_str(style
, val
, str
, len
, fmt
, mach
));
510 return (elfcap_sf1_to_str(style
, val
, str
, len
, fmt
, mach
));
513 return (elfcap_hw2_to_str(style
, val
, str
, len
, fmt
, mach
));
517 return (ELFCAP_ERR_UNKTAG
);
521 * Determine a capabilities value from a capabilities string.
524 value(elfcap_style_t style
, const char *str
, const elfcap_desc_t
*cdp
,
527 const elfcap_str_t
*nstr
;
531 for (num
= 0; num
< cnum
; num
++) {
533 * Skip "reserved" bits. These are unassigned bits in the
534 * middle of the assigned range.
536 if (cdp
[num
].c_val
== 0)
539 if ((err
= get_str_desc(style
, &cdp
[num
], &nstr
)) != 0)
541 if (style
& ELFCAP_STYLE_F_ICMP
) {
542 if (strcasecmp(str
, nstr
->s_str
) == 0)
543 return (cdp
[num
].c_val
);
545 if (strcmp(str
, nstr
->s_str
) == 0)
546 return (cdp
[num
].c_val
);
554 elfcap_sf1_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
556 return (value(style
, str
, &sf1
[0], ELFCAP_NUM_SF1
));
560 elfcap_hw1_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
562 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
563 return (value(style
, str
, &hw1_386
[0], ELFCAP_NUM_HW1_386
));
565 if ((mach
== EM_SPARC
) || (mach
== EM_SPARC32PLUS
) ||
566 (mach
== EM_SPARCV9
))
567 return (value(style
, str
, hw1_sparc
, ELFCAP_NUM_HW1_SPARC
));
572 elfcap_hw2_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
574 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
575 return (value(style
, str
, &hw2_386
[0], ELFCAP_NUM_HW2_386
));
581 * Given a capability tag type and value, return the capabilities values
582 * contained in the string.
585 elfcap_tag_from_str(elfcap_style_t style
, uint64_t tag
, const char *str
,
590 return (elfcap_hw1_from_str(style
, str
, mach
));
593 return (elfcap_sf1_from_str(style
, str
, mach
));
596 return (elfcap_hw2_from_str(style
, str
, mach
));
603 * These functions allow the caller to get direct access to the
606 const elfcap_desc_t
*
607 elfcap_getdesc_hw1_sparc(void)
612 const elfcap_desc_t
*
613 elfcap_getdesc_hw1_386(void)
618 const elfcap_desc_t
*
619 elfcap_getdesc_sf1(void)