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) 2018, 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"),
344 AV_386_2_AVX512F
, STRDESC("AV_386_2_AVX512F"),
345 STRDESC("AVX512F"), STRDESC("avx512f"),
348 AV_386_2_AVX512DQ
, STRDESC("AV_386_2_AVX512DQ"),
349 STRDESC("AVX512DQ"), STRDESC("avx512dq"),
352 AV_386_2_AVX512IFMA
, STRDESC("AV_386_2_AVX512IFMA"),
353 STRDESC("AVX512IFMA"), STRDESC("avx512ifma"),
356 AV_386_2_AVX512PF
, STRDESC("AV_386_2_AVX512PF"),
357 STRDESC("AVX512PF"), STRDESC("avx512pf"),
360 AV_386_2_AVX512ER
, STRDESC("AV_386_2_AVX512ER"),
361 STRDESC("AVX512ER"), STRDESC("avx512er"),
364 AV_386_2_AVX512CD
, STRDESC("AV_386_2_AVX512CD"),
365 STRDESC("AVX512CD"), STRDESC("avx512cd"),
368 AV_386_2_AVX512BW
, STRDESC("AV_386_2_AVX512BW"),
369 STRDESC("AVX512BW"), STRDESC("avx512bw"),
372 AV_386_2_AVX512VL
, STRDESC("AV_386_2_AVX512VL"),
373 STRDESC("AVX512VL"), STRDESC("avx512vl"),
376 AV_386_2_AVX512VBMI
, STRDESC("AV_386_2_AVX512VBMI"),
377 STRDESC("AVX512VBMI"), STRDESC("avx512vbmi"),
380 AV_386_2_AVX512VPOPCDQ
, STRDESC("AV_386_2_AVX512_VPOPCDQ"),
381 STRDESC("AVX512_VPOPCDQ"), STRDESC("avx512_vpopcntdq"),
384 AV_386_2_AVX512_4NNIW
, STRDESC("AV_386_2_AVX512_4NNIW"),
385 STRDESC("AVX512_4NNIW"), STRDESC("avx512_4nniw"),
388 AV_386_2_AVX512_4FMAPS
, STRDESC("AV_386_2_AVX512_4FMAPS"),
389 STRDESC("AVX512_4FMAPS"), STRDESC("avx512_4fmaps"),
392 AV_386_2_SHA
, STRDESC("AV_386_2_SHA"),
393 STRDESC("SHA"), STRDESC("sha"),
398 * Concatenate a token to the string buffer. This can be a capabilities token
399 * or a separator token.
402 token(char **ostr
, size_t *olen
, const elfcap_str_t
*nstr
)
404 if (*olen
< nstr
->s_len
)
405 return (ELFCAP_ERR_BUFOVFL
);
407 (void) strcat(*ostr
, nstr
->s_str
);
408 *ostr
+= nstr
->s_len
;
409 *olen
-= nstr
->s_len
;
411 return (ELFCAP_ERR_NONE
);
415 get_str_desc(elfcap_style_t style
, const elfcap_desc_t
*cdp
,
416 const elfcap_str_t
**ret_str
)
418 switch (ELFCAP_STYLE_MASK(style
)) {
419 case ELFCAP_STYLE_FULL
:
420 *ret_str
= &cdp
->c_full
;
422 case ELFCAP_STYLE_UC
:
423 *ret_str
= &cdp
->c_uc
;
425 case ELFCAP_STYLE_LC
:
426 *ret_str
= &cdp
->c_lc
;
429 return (ELFCAP_ERR_INVSTYLE
);
432 return (ELFCAP_ERR_NONE
);
437 * Expand a capabilities value into the strings defined in the associated
438 * capabilities descriptor.
441 expand(elfcap_style_t style
, elfcap_mask_t val
, const elfcap_desc_t
*cdp
,
442 uint_t cnum
, char *str
, size_t slen
, elfcap_fmt_t fmt
)
446 const elfcap_str_t
*nstr
;
449 return (ELFCAP_ERR_NONE
);
451 for (cnt
= cnum
; cnt
> 0; cnt
--) {
452 uint_t mask
= cdp
[cnt
- 1].c_val
;
454 if ((val
& mask
) != 0) {
455 if (follow
++ && ((err
= token(&str
, &slen
,
456 &format
[fmt
])) != ELFCAP_ERR_NONE
))
459 err
= get_str_desc(style
, &cdp
[cnt
- 1], &nstr
);
460 if (err
!= ELFCAP_ERR_NONE
)
462 if ((err
= token(&str
, &slen
, nstr
)) != ELFCAP_ERR_NONE
)
470 * If there are any unknown bits remaining display the numeric value.
473 if (follow
&& ((err
= token(&str
, &slen
, &format
[fmt
])) !=
477 (void) snprintf(str
, slen
, "0x%x", val
);
479 return (ELFCAP_ERR_NONE
);
483 * Expand a CA_SUNW_HW_1 value.
486 elfcap_hw1_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
487 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
490 * Initialize the string buffer, and validate the format request.
493 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
494 return (ELFCAP_ERR_INVFMT
);
496 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
497 return (expand(style
, val
, &hw1_386
[0], ELFCAP_NUM_HW1_386
,
500 if ((mach
== EM_SPARC
) || (mach
== EM_SPARC32PLUS
) ||
501 (mach
== EM_SPARCV9
))
502 return (expand(style
, val
, hw1_sparc
, ELFCAP_NUM_HW1_SPARC
,
505 return (ELFCAP_ERR_UNKMACH
);
509 * Expand a CA_SUNW_HW_2 value.
512 elfcap_hw2_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
513 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
516 * Initialize the string buffer, and validate the format request.
519 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
520 return (ELFCAP_ERR_INVFMT
);
522 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
523 return (expand(style
, val
, &hw2_386
[0], ELFCAP_NUM_HW2_386
,
526 return (expand(style
, val
, NULL
, 0, str
, len
, fmt
));
530 * Expand a CA_SUNW_SF_1 value. Note, that at present these capabilities are
531 * common across all platforms. The use of "mach" is therefore redundant, but
532 * is retained for compatibility with the interface of elfcap_hw1_to_str(), and
533 * possible future expansion.
537 elfcap_sf1_to_str(elfcap_style_t style
, elfcap_mask_t val
, char *str
,
538 size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
541 * Initialize the string buffer, and validate the format request.
544 if ((fmt
< 0) || (fmt
>= FORMAT_NELTS
))
545 return (ELFCAP_ERR_INVFMT
);
547 return (expand(style
, val
, &sf1
[0], ELFCAP_NUM_SF1
, str
, len
, fmt
));
551 * Given a capability tag type and value, map it to a string representation.
554 elfcap_tag_to_str(elfcap_style_t style
, uint64_t tag
, elfcap_mask_t val
,
555 char *str
, size_t len
, elfcap_fmt_t fmt
, ushort_t mach
)
559 return (elfcap_hw1_to_str(style
, val
, str
, len
, fmt
, mach
));
562 return (elfcap_sf1_to_str(style
, val
, str
, len
, fmt
, mach
));
565 return (elfcap_hw2_to_str(style
, val
, str
, len
, fmt
, mach
));
569 return (ELFCAP_ERR_UNKTAG
);
573 * Determine a capabilities value from a capabilities string.
576 value(elfcap_style_t style
, const char *str
, const elfcap_desc_t
*cdp
,
579 const elfcap_str_t
*nstr
;
583 for (num
= 0; num
< cnum
; num
++) {
585 * Skip "reserved" bits. These are unassigned bits in the
586 * middle of the assigned range.
588 if (cdp
[num
].c_val
== 0)
591 if ((err
= get_str_desc(style
, &cdp
[num
], &nstr
)) != 0)
593 if (style
& ELFCAP_STYLE_F_ICMP
) {
594 if (strcasecmp(str
, nstr
->s_str
) == 0)
595 return (cdp
[num
].c_val
);
597 if (strcmp(str
, nstr
->s_str
) == 0)
598 return (cdp
[num
].c_val
);
606 elfcap_sf1_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
608 return (value(style
, str
, &sf1
[0], ELFCAP_NUM_SF1
));
612 elfcap_hw1_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
614 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
615 return (value(style
, str
, &hw1_386
[0], ELFCAP_NUM_HW1_386
));
617 if ((mach
== EM_SPARC
) || (mach
== EM_SPARC32PLUS
) ||
618 (mach
== EM_SPARCV9
))
619 return (value(style
, str
, hw1_sparc
, ELFCAP_NUM_HW1_SPARC
));
624 elfcap_hw2_from_str(elfcap_style_t style
, const char *str
, ushort_t mach
)
626 if ((mach
== EM_386
) || (mach
== EM_IA_64
) || (mach
== EM_AMD64
))
627 return (value(style
, str
, &hw2_386
[0], ELFCAP_NUM_HW2_386
));
633 * Given a capability tag type and value, return the capabilities values
634 * contained in the string.
637 elfcap_tag_from_str(elfcap_style_t style
, uint64_t tag
, const char *str
,
642 return (elfcap_hw1_from_str(style
, str
, mach
));
645 return (elfcap_sf1_from_str(style
, str
, mach
));
648 return (elfcap_hw2_from_str(style
, str
, mach
));
655 * These functions allow the caller to get direct access to the
658 const elfcap_desc_t
*
659 elfcap_getdesc_hw1_sparc(void)
664 const elfcap_desc_t
*
665 elfcap_getdesc_hw1_386(void)
670 const elfcap_desc_t
*
671 elfcap_getdesc_sf1(void)