1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * This implements psrinfo(1M), a utility to report various information
18 * about processors, cores, and threads (virtual cpus). This is mostly
19 * intended for human consumption - this utility doesn't do much more than
20 * simply process kstats for human readability.
21 *
22 * All the relevant kstats are in the cpu_info kstat module.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <kstat.h>
30 #include <libintl.h>
31 #include <locale.h>
32 #include <libgen.h>
33 #include <ctype.h>
80
81 struct vcpu {
82 struct link v_link;
83
84 struct link v_link_core;
85 struct link v_link_pchip;
86
87 int v_doit;
88
89 struct pchip *v_pchip;
90 struct core *v_core;
91
92 char *v_state;
93 long v_state_begin;
94 char *v_cpu_type;
95 char *v_fpu_type;
96 long v_clock_mhz;
97 long v_pchip_id; /* 1 per socket */
98 char *v_impl;
99 char *v_brand;
100 long v_core_id; /* n per chip_id */
101 };
102
103 static struct link *pchips = NULL;
104 static struct link *cores = NULL;
105 static struct link *vcpus = NULL;
106
107 static const char *cmdname;
108
109 static void
110 usage(char *msg)
111 {
112 if (msg != NULL)
113 (void) fprintf(stderr, "%s: %s\n", cmdname, msg);
114 (void) fprintf(stderr, _("usage: \n" \
115 "\t%s [-v] [-p] [processor_id ...]\n" \
116 "\t%s -s [-p] processor_id\n"), cmdname, cmdname);
117 exit(2);
118 }
119
251 _("processor"));
252 } else {
253 (void) printf(_("%s has %d %s and %d virtual %s"),
254 _("The physical processor"),
255 chip->p_ncore, _("cores"),
256 chip->p_nvcpu,
257 chip->p_nvcpu > 1 ?
258 _("processors") : _("processor"));
259 }
260
261 print_links(chip->p_vcpus);
262 (void) putchar('\n');
263
264 if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
265 if (strlen(vcpu->v_impl)) {
266 (void) printf(" %s\n", vcpu->v_impl);
267 }
268 if (((len = strlen(vcpu->v_brand)) != 0) &&
269 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
270 (void) printf("\t%s", vcpu->v_brand);
271 (void) putchar('\n');
272 } else {
273 for (l2 = chip->p_cores; l2; l2 = l2->l_next) {
274 core = l2->l_ptr;
275 (void) printf(_(" %s has %d virtual %s"),
276 _("The core"),
277 core->c_nvcpu,
278 chip->p_nvcpu > 1 ?
279 _("processors") : _("processor"));
280 print_links(core->c_vcpus);
281 (void) putchar('\n');
282 }
283 if (strlen(vcpu->v_impl)) {
284 (void) printf(" %s\n", vcpu->v_impl);
285 }
286 if (((len = strlen(vcpu->v_brand)) != 0) &&
287 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
288 (void) printf(" %s\n", vcpu->v_brand);
289 }
290 }
490 vc->v_cpu_type = mystrdup(knp->value.c);
491 }
492 if ((knp = kstat_data_lookup(ksp, "fpu_type")) != NULL) {
493 vc->v_fpu_type = mystrdup(knp->value.c);
494 }
495
496 if ((knp = kstat_data_lookup(ksp, "state_begin")) != NULL) {
497 vc->v_state_begin = knp->value.l;
498 }
499
500 if ((knp = kstat_data_lookup(ksp, "clock_MHz")) != NULL) {
501 vc->v_clock_mhz = knp->value.l;
502 }
503
504 if ((knp = kstat_data_lookup(ksp, "brand")) == NULL) {
505 vc->v_brand = _("(unknown)");
506 } else {
507 vc->v_brand = mystrdup(knp->value.str.addr.ptr);
508 }
509
510 if ((knp = kstat_data_lookup(ksp, "implementation")) == NULL) {
511 vc->v_impl = _("(unknown)");
512 } else {
513 vc->v_impl = mystrdup(knp->value.str.addr.ptr);
514 }
515 /*
516 * Legacy code removed the chipid and cpuid fields... we
517 * do the same for compatibility. Note that the original
518 * pattern is a bit strange, and we have to emulate this because
519 * on SPARC we *do* emit these. The original pattern we are
520 * emulating is: $impl =~ s/(cpuid|chipid)\s*\w+\s+//;
521 */
522 if ((s = strstr(vc->v_impl, "chipid")) != NULL) {
523 char *x = s + strlen("chipid");
524 while (isspace(*x))
525 x++;
526 if ((!isalnum(*x)) && (*x != '_'))
527 goto nochipid;
528 while (isalnum(*x) || (*x == '_'))
529 x++;
|
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
14 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
15 */
16
17 /*
18 * This implements psrinfo(1M), a utility to report various information
19 * about processors, cores, and threads (virtual cpus). This is mostly
20 * intended for human consumption - this utility doesn't do much more than
21 * simply process kstats for human readability.
22 *
23 * All the relevant kstats are in the cpu_info kstat module.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <kstat.h>
31 #include <libintl.h>
32 #include <locale.h>
33 #include <libgen.h>
34 #include <ctype.h>
81
82 struct vcpu {
83 struct link v_link;
84
85 struct link v_link_core;
86 struct link v_link_pchip;
87
88 int v_doit;
89
90 struct pchip *v_pchip;
91 struct core *v_core;
92
93 char *v_state;
94 long v_state_begin;
95 char *v_cpu_type;
96 char *v_fpu_type;
97 long v_clock_mhz;
98 long v_pchip_id; /* 1 per socket */
99 char *v_impl;
100 char *v_brand;
101 char *v_socket;
102 long v_core_id; /* n per chip_id */
103 };
104
105 static struct link *pchips = NULL;
106 static struct link *cores = NULL;
107 static struct link *vcpus = NULL;
108
109 static const char *cmdname;
110
111 static void
112 usage(char *msg)
113 {
114 if (msg != NULL)
115 (void) fprintf(stderr, "%s: %s\n", cmdname, msg);
116 (void) fprintf(stderr, _("usage: \n" \
117 "\t%s [-v] [-p] [processor_id ...]\n" \
118 "\t%s -s [-p] processor_id\n"), cmdname, cmdname);
119 exit(2);
120 }
121
253 _("processor"));
254 } else {
255 (void) printf(_("%s has %d %s and %d virtual %s"),
256 _("The physical processor"),
257 chip->p_ncore, _("cores"),
258 chip->p_nvcpu,
259 chip->p_nvcpu > 1 ?
260 _("processors") : _("processor"));
261 }
262
263 print_links(chip->p_vcpus);
264 (void) putchar('\n');
265
266 if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
267 if (strlen(vcpu->v_impl)) {
268 (void) printf(" %s\n", vcpu->v_impl);
269 }
270 if (((len = strlen(vcpu->v_brand)) != 0) &&
271 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
272 (void) printf("\t%s", vcpu->v_brand);
273 if (strcmp(vcpu->v_socket, "Unknown") != 0)
274 (void) printf("\t[ %s: %s ]", _("Socket"),
275 vcpu->v_socket);
276 (void) putchar('\n');
277 } else {
278 for (l2 = chip->p_cores; l2; l2 = l2->l_next) {
279 core = l2->l_ptr;
280 (void) printf(_(" %s has %d virtual %s"),
281 _("The core"),
282 core->c_nvcpu,
283 chip->p_nvcpu > 1 ?
284 _("processors") : _("processor"));
285 print_links(core->c_vcpus);
286 (void) putchar('\n');
287 }
288 if (strlen(vcpu->v_impl)) {
289 (void) printf(" %s\n", vcpu->v_impl);
290 }
291 if (((len = strlen(vcpu->v_brand)) != 0) &&
292 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
293 (void) printf(" %s\n", vcpu->v_brand);
294 }
295 }
495 vc->v_cpu_type = mystrdup(knp->value.c);
496 }
497 if ((knp = kstat_data_lookup(ksp, "fpu_type")) != NULL) {
498 vc->v_fpu_type = mystrdup(knp->value.c);
499 }
500
501 if ((knp = kstat_data_lookup(ksp, "state_begin")) != NULL) {
502 vc->v_state_begin = knp->value.l;
503 }
504
505 if ((knp = kstat_data_lookup(ksp, "clock_MHz")) != NULL) {
506 vc->v_clock_mhz = knp->value.l;
507 }
508
509 if ((knp = kstat_data_lookup(ksp, "brand")) == NULL) {
510 vc->v_brand = _("(unknown)");
511 } else {
512 vc->v_brand = mystrdup(knp->value.str.addr.ptr);
513 }
514
515 if ((knp = kstat_data_lookup(ksp, "socket_type")) == NULL) {
516 vc->v_socket = "Unknown";
517 } else {
518 vc->v_socket = mystrdup(knp->value.str.addr.ptr);
519 }
520
521 if ((knp = kstat_data_lookup(ksp, "implementation")) == NULL) {
522 vc->v_impl = _("(unknown)");
523 } else {
524 vc->v_impl = mystrdup(knp->value.str.addr.ptr);
525 }
526 /*
527 * Legacy code removed the chipid and cpuid fields... we
528 * do the same for compatibility. Note that the original
529 * pattern is a bit strange, and we have to emulate this because
530 * on SPARC we *do* emit these. The original pattern we are
531 * emulating is: $impl =~ s/(cpuid|chipid)\s*\w+\s+//;
532 */
533 if ((s = strstr(vc->v_impl, "chipid")) != NULL) {
534 char *x = s + strlen("chipid");
535 while (isspace(*x))
536 x++;
537 if ((!isalnum(*x)) && (*x != '_'))
538 goto nochipid;
539 while (isalnum(*x) || (*x == '_'))
540 x++;
|