3414 Need a new word of AT_SUN_HWCAP bits
[unleashed.git] / usr / src / cmd / isainfo / isainfo.c
blobadf2f14dc9986d0ae0b77d0e6b792a401be2626d
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
30 #include <sys/types.h>
31 #include <sys/systeminfo.h>
32 #include <sys/utsname.h>
33 #include <sys/stat.h>
35 #include <sys/auxv.h>
36 #include <sys/cpuid_drv.h>
37 #include <sys/elf.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <libintl.h>
45 #include <locale.h>
46 #include <fcntl.h>
48 #include <elfcap.h>
50 static const char dev_cpu_self_cpuid[] = "/dev/" CPUID_SELF_NAME;
51 static char *pgmname;
52 static int mode = 0;
54 #define BITS_MODE 0x1
55 #define NATIVE_MODE 0x2
56 #define KERN_MODE 0x4
57 #define VERBOSE_MODE 0x8
58 #define EXTN_MODE 0x10
60 static char *
61 getsysinfo(int cmd)
63 char *buf;
64 size_t bufsize = 20; /* wild guess */
65 long ret;
67 if ((buf = malloc(bufsize)) == NULL)
68 return (NULL);
69 do {
70 ret = sysinfo(cmd, buf, bufsize);
71 if (ret == -1)
72 return (NULL);
73 if (ret > bufsize) {
74 bufsize = ret;
75 buf = realloc(buf, bufsize);
76 } else
77 break;
78 } while (buf != NULL);
80 return (buf);
84 * Classify isa's as to bitness of the corresponding ABIs.
85 * isa's which have no "official" Solaris ABI are returned
86 * unrecognised i.e. "zero bit".
88 static uint_t
89 bitness(const char *isaname)
91 if (strcmp(isaname, "sparc") == 0 ||
92 strcmp(isaname, "i386") == 0)
93 return (32);
95 if (strcmp(isaname, "sparcv9") == 0 ||
96 strcmp(isaname, "amd64") == 0)
97 return (64);
99 return (0);
102 static char *
103 report_abi(int cmd, const char *vfmt)
105 uint_t bits;
106 char *isa;
108 if ((isa = getsysinfo(cmd)) == NULL)
109 return (0);
110 if ((bits = bitness(isa)) == 0) {
111 (void) fprintf(stderr,
112 gettext("%s: unable to identify isa '%s'!\n"),
113 pgmname, isa);
114 exit(3);
117 if (mode & VERBOSE_MODE)
118 (void) printf(vfmt, bits, isa);
119 else if (mode & BITS_MODE)
120 (void) printf("%d\n", bits);
121 else if (mode & (NATIVE_MODE|KERN_MODE))
122 (void) printf("%s\n", isa);
123 else
124 (void) printf("%s", isa);
125 return (isa);
129 * Classify isas as their machine type.
131 static ushort_t
132 machtype(const char *isaname)
134 if (strcmp(isaname, "sparc") == 0)
135 return (EM_SPARC);
136 if (strcmp(isaname, "sparcv9") == 0)
137 return (EM_SPARCV9);
138 if (strcmp(isaname, "i386") == 0)
139 return (EM_386);
140 if (strcmp(isaname, "amd64") == 0)
141 return (EM_AMD64);
143 return (0);
146 static void
147 report_hwcap(int d, const char *isa)
149 struct cpuid_get_hwcap __cgh, *cgh = &__cgh;
150 char buffer[1024], cap2[1024];
152 cgh->cgh_archname = (char *)isa;
153 if (ioctl(d, CPUID_GET_HWCAP, cgh) != 0)
154 return;
156 (void) elfcap_hw1_to_str(ELFCAP_STYLE_LC, cgh->cgh_hwcap[0],
157 buffer, sizeof (buffer), ELFCAP_FMT_SNGSPACE, machtype(isa));
159 if (cgh->cgh_hwcap[1] != 0)
160 (void) elfcap_hw2_to_str(ELFCAP_STYLE_LC, cgh->cgh_hwcap[1],
161 cap2, sizeof (cap2), ELFCAP_FMT_SNGSPACE, machtype(isa));
162 else
163 cap2[0] = '\0';
165 if (mode & EXTN_MODE) {
166 (void) printf(":");
167 if (cgh->cgh_hwcap[1] != NULL)
168 (void) printf(" %s", cap2);
169 (void) printf(" %s", buffer);
170 (void) printf("\n");
171 } else {
172 char *p;
173 int linecnt = 0;
175 for (p = strtok(cap2, " "); p; p = strtok(NULL, " ")) {
176 if (linecnt + strlen(p) > 68) {
177 (void) printf("\n");
178 linecnt = 0;
180 if (linecnt == 0)
181 linecnt = printf("\t");
182 linecnt += printf("%s ", p);
185 for (p = strtok(buffer, " "); p; p = strtok(NULL, " ")) {
186 if (linecnt + strlen(p) > 68) {
187 (void) printf("\n");
188 linecnt = 0;
190 if (linecnt == 0)
191 linecnt = printf("\t");
192 linecnt += printf("%s ", p);
195 if (linecnt != 0)
196 (void) printf("\n");
200 #if !defined(TEXT_DOMAIN)
201 #define TEXT_DOMAIN "SYS_TEST"
202 #endif
205 main(int argc, char *argv[])
207 int errflg = 0;
208 int c;
209 char *vfmt;
210 char *isa, *isa32;
211 int d = -1;
212 const int excl_modes = /* exclusive mode settings */
213 NATIVE_MODE | BITS_MODE | KERN_MODE | EXTN_MODE;
215 (void) setlocale(LC_ALL, "");
216 (void) textdomain(TEXT_DOMAIN);
218 if ((pgmname = strrchr(*argv, '/')) == 0)
219 pgmname = argv[0];
220 else
221 pgmname++;
223 while ((c = getopt(argc, argv, "nbkvx")) != EOF)
224 switch (c) {
225 case 'n':
226 if (mode & excl_modes)
227 errflg++;
228 mode |= NATIVE_MODE;
229 break;
230 case 'b':
231 if (mode & excl_modes)
232 errflg++;
233 mode |= BITS_MODE;
234 break;
235 case 'k':
236 if (mode & excl_modes)
237 errflg++;
238 mode |= KERN_MODE;
239 break;
240 case 'x':
241 if (mode & excl_modes || mode & VERBOSE_MODE)
242 errflg++;
243 mode |= EXTN_MODE;
244 break;
245 case 'v':
246 if (mode & EXTN_MODE)
247 errflg++;
248 mode |= VERBOSE_MODE;
249 break;
250 case '?':
251 default:
252 errflg++;
253 break;
256 if (errflg || optind != argc) {
257 (void) fprintf(stderr,
258 gettext("usage: %s [ [-v] [-b | -n | -k] | [-x] ]\n"),
259 pgmname);
260 return (1);
264 * We use dev_cpu_self_cpuid for discovering hardware capabilities;
265 * but we only complain if we can't open it if we've been
266 * asked to report on those capabilities.
268 if ((mode & (VERBOSE_MODE|EXTN_MODE)) != 0 &&
269 (d = open(dev_cpu_self_cpuid, O_RDONLY)) == -1)
270 perror(dev_cpu_self_cpuid), exit(1);
272 if (mode & KERN_MODE) {
273 vfmt = gettext("%d-bit %s kernel modules\n");
274 (void) report_abi(SI_ARCHITECTURE_K, vfmt);
275 return (0);
278 vfmt = gettext("%d-bit %s applications\n");
280 if (mode & (BITS_MODE | NATIVE_MODE)) {
281 if ((isa = report_abi(SI_ARCHITECTURE_64, vfmt)) == NULL)
282 isa = report_abi(SI_ARCHITECTURE_32, vfmt);
283 if (isa != NULL && (mode & VERBOSE_MODE) != 0)
284 report_hwcap(d, isa);
285 } else {
286 if ((isa = report_abi(SI_ARCHITECTURE_64, vfmt)) != NULL) {
287 if (mode & (EXTN_MODE|VERBOSE_MODE))
288 report_hwcap(d, isa);
289 else
290 (void) putchar(' ');
293 if ((isa32 = report_abi(SI_ARCHITECTURE_32, vfmt)) != NULL) {
294 if (mode & (EXTN_MODE|VERBOSE_MODE))
295 report_hwcap(d, isa32);
298 if ((isa32 != NULL || isa != NULL) &&
299 (mode & (EXTN_MODE|VERBOSE_MODE)) == 0)
300 (void) putchar('\n');
303 return (0);