xref: /illumos-gate/usr/src/cmd/psrinfo/psrinfo.c (revision db6ea8e6)
1a3477ee4SGarrett D'Amore /*
2a3477ee4SGarrett D'Amore  * This file and its contents are supplied under the terms of the
3a3477ee4SGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
4a3477ee4SGarrett D'Amore  * You may only use this file in accordance with the terms of version
5a3477ee4SGarrett D'Amore  * 1.0 of the CDDL.
6a3477ee4SGarrett D'Amore  *
7a3477ee4SGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
8a3477ee4SGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
9a3477ee4SGarrett D'Amore  * http://www.illumos.org/license/CDDL.
10a3477ee4SGarrett D'Amore  */
11a3477ee4SGarrett D'Amore 
12a3477ee4SGarrett D'Amore /*
13a3477ee4SGarrett D'Amore  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
1448ac0edbSHans Rosenfeld  * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
15c3377ee9SJohn Levon  * Copyright 2019 Joyent, Inc.
16*db6ea8e6SKeith M Wesolowski  * Copyright 2022 Oxide Computer Co.
17a3477ee4SGarrett D'Amore  */
18a3477ee4SGarrett D'Amore 
19a3477ee4SGarrett D'Amore /*
20bbf21555SRichard Lowe  * This implements psrinfo(8), a utility to report various information
21a3477ee4SGarrett D'Amore  * about processors, cores, and threads (virtual cpus).  This is mostly
22a3477ee4SGarrett D'Amore  * intended for human consumption - this utility doesn't do much more than
23a3477ee4SGarrett D'Amore  * simply process kstats for human readability.
24a3477ee4SGarrett D'Amore  *
25a3477ee4SGarrett D'Amore  * All the relevant kstats are in the cpu_info kstat module.
26a3477ee4SGarrett D'Amore  */
27a3477ee4SGarrett D'Amore 
28c3377ee9SJohn Levon #include <sys/sysmacros.h>
29c3377ee9SJohn Levon 
30c3377ee9SJohn Levon #include <stdbool.h>
31a3477ee4SGarrett D'Amore #include <stdio.h>
32a3477ee4SGarrett D'Amore #include <stdlib.h>
33a3477ee4SGarrett D'Amore #include <unistd.h>
34a3477ee4SGarrett D'Amore #include <string.h>
35a3477ee4SGarrett D'Amore #include <kstat.h>
36a3477ee4SGarrett D'Amore #include <libintl.h>
37a3477ee4SGarrett D'Amore #include <locale.h>
38a3477ee4SGarrett D'Amore #include <libgen.h>
39a3477ee4SGarrett D'Amore #include <ctype.h>
40a3477ee4SGarrett D'Amore #include <errno.h>
41c3377ee9SJohn Levon #include <err.h>
42c3377ee9SJohn Levon 
43c3377ee9SJohn Levon #include <libdevinfo.h>
44a3477ee4SGarrett D'Amore 
45a3477ee4SGarrett D'Amore #define	_(x)	gettext(x)
46a3477ee4SGarrett D'Amore #if XGETTEXT
47a3477ee4SGarrett D'Amore 	/* These CPU states are here for benefit of xgettext */
48a3477ee4SGarrett D'Amore 	_("on-line")
49a3477ee4SGarrett D'Amore 	_("off-line")
50a3477ee4SGarrett D'Amore 	_("faulted")
51a3477ee4SGarrett D'Amore 	_("powered-off")
52a3477ee4SGarrett D'Amore 	_("no-intr")
53a3477ee4SGarrett D'Amore 	_("spare")
54a3477ee4SGarrett D'Amore 	_("unknown")
55c3377ee9SJohn Levon 	_("disabled")
56a3477ee4SGarrett D'Amore #endif
57a3477ee4SGarrett D'Amore 
58a3477ee4SGarrett D'Amore /*
59a3477ee4SGarrett D'Amore  * We deal with sorted linked lists, where the sort key is usually the
60a3477ee4SGarrett D'Amore  * cpu id, core id, or chip id.  We generalize this with simple node.
61a3477ee4SGarrett D'Amore  */
62a3477ee4SGarrett D'Amore struct link {
63a3477ee4SGarrett D'Amore 	long		l_id;
64a3477ee4SGarrett D'Amore 	struct link	*l_next;
65a3477ee4SGarrett D'Amore 	void		*l_ptr;
66a3477ee4SGarrett D'Amore };
67a3477ee4SGarrett D'Amore 
68a3477ee4SGarrett D'Amore /*
69a3477ee4SGarrett D'Amore  * A physical chip.  A chip can contain multiple cores and virtual cpus.
70a3477ee4SGarrett D'Amore  */
71a3477ee4SGarrett D'Amore struct pchip {
72a3477ee4SGarrett D'Amore 	struct link	p_link;
73a3477ee4SGarrett D'Amore 	int		p_ncore;
74a3477ee4SGarrett D'Amore 	int		p_nvcpu;
75a3477ee4SGarrett D'Amore 	struct link	*p_cores;
76a3477ee4SGarrett D'Amore 	struct link	*p_vcpus;
77a3477ee4SGarrett D'Amore 	int		p_doit;
78a3477ee4SGarrett D'Amore };
79a3477ee4SGarrett D'Amore 
80a3477ee4SGarrett D'Amore struct core {
81a3477ee4SGarrett D'Amore 	struct link	c_link;
82a3477ee4SGarrett D'Amore 	struct link	c_link_pchip;
83a3477ee4SGarrett D'Amore 
84a3477ee4SGarrett D'Amore 	int		c_nvcpu;
85a3477ee4SGarrett D'Amore 	int		c_doit;
86a3477ee4SGarrett D'Amore 
87a3477ee4SGarrett D'Amore 	struct pchip	*c_pchip;
88a3477ee4SGarrett D'Amore 	struct link	*c_vcpus;
89a3477ee4SGarrett D'Amore };
90a3477ee4SGarrett D'Amore 
91a3477ee4SGarrett D'Amore struct vcpu {
92a3477ee4SGarrett D'Amore 	struct link	v_link;
93a3477ee4SGarrett D'Amore 
94a3477ee4SGarrett D'Amore 	struct link	v_link_core;
95a3477ee4SGarrett D'Amore 	struct link	v_link_pchip;
96a3477ee4SGarrett D'Amore 
97a3477ee4SGarrett D'Amore 	int		v_doit;
98a3477ee4SGarrett D'Amore 
99a3477ee4SGarrett D'Amore 	struct pchip	*v_pchip;
100a3477ee4SGarrett D'Amore 	struct core	*v_core;
101a3477ee4SGarrett D'Amore 
102a3477ee4SGarrett D'Amore 	char		*v_state;
103a3477ee4SGarrett D'Amore 	long		v_state_begin;
104a3477ee4SGarrett D'Amore 	char		*v_cpu_type;
105a3477ee4SGarrett D'Amore 	char		*v_fpu_type;
106a3477ee4SGarrett D'Amore 	long		v_clock_mhz;
107a3477ee4SGarrett D'Amore 	long		v_pchip_id;	/* 1 per socket */
108a3477ee4SGarrett D'Amore 	char		*v_impl;
109a3477ee4SGarrett D'Amore 	char		*v_brand;
11048ac0edbSHans Rosenfeld 	char		*v_socket;
111a3477ee4SGarrett D'Amore 	long		v_core_id;	/* n per chip_id */
112a3477ee4SGarrett D'Amore };
113a3477ee4SGarrett D'Amore 
114a3477ee4SGarrett D'Amore static struct link *pchips = NULL;
115a3477ee4SGarrett D'Amore static struct link *cores = NULL;
116a3477ee4SGarrett D'Amore static struct link *vcpus = NULL;
117a3477ee4SGarrett D'Amore 
118c3377ee9SJohn Levon static uint_t nr_cpus;
119c3377ee9SJohn Levon static uint_t nr_cores;
120c3377ee9SJohn Levon static uint_t nr_chips;
121c3377ee9SJohn Levon 
122a3477ee4SGarrett D'Amore static const char *cmdname;
123a3477ee4SGarrett D'Amore 
124a3477ee4SGarrett D'Amore static void
usage(char * msg)125a3477ee4SGarrett D'Amore usage(char *msg)
126a3477ee4SGarrett D'Amore {
127a3477ee4SGarrett D'Amore 	if (msg != NULL)
128a3477ee4SGarrett D'Amore 		(void) fprintf(stderr, "%s: %s\n", cmdname, msg);
129c3377ee9SJohn Levon 	(void) fprintf(stderr, _("usage: \n"
130c3377ee9SJohn Levon 	    "\t%s -r propname\n"
131c3377ee9SJohn Levon 	    "\t%s [-v] [-p] [processor_id ...]\n"
132c3377ee9SJohn Levon 	    "\t%s -s [-p] processor_id\n"
133c3377ee9SJohn Levon 	    "\t%s -t [-S <state> | -c | -p]\n"),
134c3377ee9SJohn Levon 	    cmdname, cmdname, cmdname, cmdname);
135a3477ee4SGarrett D'Amore 	exit(2);
136a3477ee4SGarrett D'Amore }
137a3477ee4SGarrett D'Amore 
138a3477ee4SGarrett D'Amore /* like perror, but includes the command name */
139a3477ee4SGarrett D'Amore static void
die(const char * msg)140a3477ee4SGarrett D'Amore die(const char *msg)
141a3477ee4SGarrett D'Amore {
142a3477ee4SGarrett D'Amore 	(void) fprintf(stderr, "%s: %s: %s\n", cmdname, msg, strerror(errno));
143a3477ee4SGarrett D'Amore 	exit(2);
144a3477ee4SGarrett D'Amore }
145a3477ee4SGarrett D'Amore 
146a3477ee4SGarrett D'Amore static char *
mystrdup(const char * src)147a3477ee4SGarrett D'Amore mystrdup(const char *src)
148a3477ee4SGarrett D'Amore {
149a3477ee4SGarrett D'Amore 	char *dst;
150a3477ee4SGarrett D'Amore 
151a3477ee4SGarrett D'Amore 	if ((dst = strdup(src)) == NULL)
152a3477ee4SGarrett D'Amore 		die(_("strdup() failed"));
153a3477ee4SGarrett D'Amore 	return (dst);
154a3477ee4SGarrett D'Amore }
155a3477ee4SGarrett D'Amore 
156a3477ee4SGarrett D'Amore static void *
zalloc(size_t size)157a3477ee4SGarrett D'Amore zalloc(size_t size)
158a3477ee4SGarrett D'Amore {
159a3477ee4SGarrett D'Amore 	void *ptr;
160a3477ee4SGarrett D'Amore 
161a3477ee4SGarrett D'Amore 	if ((ptr = calloc(1, size)) == NULL)
162a3477ee4SGarrett D'Amore 		die(_("calloc() failed"));
163a3477ee4SGarrett D'Amore 	return (ptr);
164a3477ee4SGarrett D'Amore }
165a3477ee4SGarrett D'Amore 
166a3477ee4SGarrett D'Amore /*
167a3477ee4SGarrett D'Amore  * Insert a new node on a list, at the insertion point given.
168a3477ee4SGarrett D'Amore  */
169a3477ee4SGarrett D'Amore static void
ins_link(struct link ** ins,struct link * item)170a3477ee4SGarrett D'Amore ins_link(struct link **ins, struct link *item)
171a3477ee4SGarrett D'Amore {
172a3477ee4SGarrett D'Amore 	item->l_next = *ins;
173a3477ee4SGarrett D'Amore 	*ins = item;
174a3477ee4SGarrett D'Amore }
175a3477ee4SGarrett D'Amore 
176a3477ee4SGarrett D'Amore /*
177a3477ee4SGarrett D'Amore  * Find an id on a sorted list.  If the requested id is not found,
178a3477ee4SGarrett D'Amore  * then the insertpt will be set (if not null) to the location where
179a3477ee4SGarrett D'Amore  * a new node should be inserted with ins_link (see above).
180a3477ee4SGarrett D'Amore  */
181a3477ee4SGarrett D'Amore static void *
find_link(void * list,int id,struct link *** insertpt)182a3477ee4SGarrett D'Amore find_link(void *list, int id, struct link ***insertpt)
183a3477ee4SGarrett D'Amore {
184a3477ee4SGarrett D'Amore 	struct link **ins = list;
185a3477ee4SGarrett D'Amore 	struct link *l;
186a3477ee4SGarrett D'Amore 
187a3477ee4SGarrett D'Amore 	while ((l = *ins) != NULL) {
188a3477ee4SGarrett D'Amore 		if (l->l_id == id)
189a3477ee4SGarrett D'Amore 			return (l->l_ptr);
190a3477ee4SGarrett D'Amore 		if (l->l_id > id)
191a3477ee4SGarrett D'Amore 			break;
192a3477ee4SGarrett D'Amore 		ins = &l->l_next;
193a3477ee4SGarrett D'Amore 	}
194a3477ee4SGarrett D'Amore 	if (insertpt != NULL)
195a3477ee4SGarrett D'Amore 		*insertpt = ins;
196a3477ee4SGarrett D'Amore 	return (NULL);
197a3477ee4SGarrett D'Amore }
198a3477ee4SGarrett D'Amore 
199a3477ee4SGarrett D'Amore /*
200a3477ee4SGarrett D'Amore  * Print the linked list of ids in parens, taking care to collapse
201a3477ee4SGarrett D'Amore  * ranges, so instead of (0 1 2 3) it should print (0-3).
202a3477ee4SGarrett D'Amore  */
203a3477ee4SGarrett D'Amore static void
print_links(struct link * l)204a3477ee4SGarrett D'Amore print_links(struct link *l)
205a3477ee4SGarrett D'Amore {
206a3477ee4SGarrett D'Amore 	int	start = -1;
207a3477ee4SGarrett D'Amore 	int	end = 0;
208a3477ee4SGarrett D'Amore 
209a3477ee4SGarrett D'Amore 	(void) printf(" (");
210a3477ee4SGarrett D'Amore 	while (l != NULL) {
211a3477ee4SGarrett D'Amore 		if (start < 0) {
212a3477ee4SGarrett D'Amore 			start = l->l_id;
213a3477ee4SGarrett D'Amore 		}
214a3477ee4SGarrett D'Amore 		end = l->l_id;
215a3477ee4SGarrett D'Amore 		if ((l->l_next == NULL) ||
216a3477ee4SGarrett D'Amore 		    (l->l_next->l_id > (l->l_id + 1))) {
217a3477ee4SGarrett D'Amore 			/* end of the contiguous group */
218a3477ee4SGarrett D'Amore 			if (start == end) {
219a3477ee4SGarrett D'Amore 				(void) printf("%d", start);
220a3477ee4SGarrett D'Amore 			} else {
221a3477ee4SGarrett D'Amore 				(void) printf("%d-%d", start, end);
222a3477ee4SGarrett D'Amore 			}
223a3477ee4SGarrett D'Amore 			if (l->l_next)
224a3477ee4SGarrett D'Amore 				(void) printf(" ");
225a3477ee4SGarrett D'Amore 			start = -1;
226a3477ee4SGarrett D'Amore 		}
227a3477ee4SGarrett D'Amore 		l = l->l_next;
228a3477ee4SGarrett D'Amore 	}
229a3477ee4SGarrett D'Amore 	(void) printf(")");
230a3477ee4SGarrett D'Amore }
231a3477ee4SGarrett D'Amore 
232a3477ee4SGarrett D'Amore static const char *
timestr(long t)233a3477ee4SGarrett D'Amore timestr(long t)
234a3477ee4SGarrett D'Amore {
235a3477ee4SGarrett D'Amore 	static char buffer[256];
236a3477ee4SGarrett D'Amore 	(void) strftime(buffer, sizeof (buffer), _("%m/%d/%Y %T"),
237a3477ee4SGarrett D'Amore 	    localtime(&t));
238a3477ee4SGarrett D'Amore 	return (buffer);
239a3477ee4SGarrett D'Amore }
240a3477ee4SGarrett D'Amore 
241a3477ee4SGarrett D'Amore static void
print_vp(int nspec)242a3477ee4SGarrett D'Amore print_vp(int nspec)
243a3477ee4SGarrett D'Amore {
244a3477ee4SGarrett D'Amore 	struct pchip *chip;
245a3477ee4SGarrett D'Amore 	struct core *core;
246a3477ee4SGarrett D'Amore 	struct vcpu *vcpu;
247a3477ee4SGarrett D'Amore 	struct link *l1, *l2;
248a3477ee4SGarrett D'Amore 	int len;
249a3477ee4SGarrett D'Amore 	for (l1 = pchips; l1; l1 = l1->l_next) {
250a3477ee4SGarrett D'Amore 
251a3477ee4SGarrett D'Amore 		chip = l1->l_ptr;
252a3477ee4SGarrett D'Amore 
253a3477ee4SGarrett D'Amore 		if ((nspec != 0) && (chip->p_doit == 0))
254a3477ee4SGarrett D'Amore 			continue;
255a3477ee4SGarrett D'Amore 
256a3477ee4SGarrett D'Amore 		vcpu = chip->p_vcpus->l_ptr;
257a3477ee4SGarrett D'Amore 
258a3477ee4SGarrett D'Amore 		/*
259a3477ee4SGarrett D'Amore 		 * Note that some of the way these strings are broken up are
260a3477ee4SGarrett D'Amore 		 * to accommodate the legacy translations so that we won't
261a3477ee4SGarrett D'Amore 		 * have to retranslate for this utility.
262a3477ee4SGarrett D'Amore 		 */
263a3477ee4SGarrett D'Amore 		if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
264a3477ee4SGarrett D'Amore 			(void) printf(_("%s has %d virtual %s"),
265a3477ee4SGarrett D'Amore 			    _("The physical processor"),
266a3477ee4SGarrett D'Amore 			    chip->p_nvcpu,
267a3477ee4SGarrett D'Amore 			    chip->p_nvcpu > 1 ?
268a3477ee4SGarrett D'Amore 			    _("processors") :
269a3477ee4SGarrett D'Amore 			    _("processor"));
270a3477ee4SGarrett D'Amore 		} else {
271a3477ee4SGarrett D'Amore 			(void) printf(_("%s has %d %s and %d virtual %s"),
272a3477ee4SGarrett D'Amore 			    _("The physical processor"),
273a3477ee4SGarrett D'Amore 			    chip->p_ncore, _("cores"),
274a3477ee4SGarrett D'Amore 			    chip->p_nvcpu,
275a3477ee4SGarrett D'Amore 			    chip->p_nvcpu > 1 ?
276a3477ee4SGarrett D'Amore 			    _("processors") : _("processor"));
277a3477ee4SGarrett D'Amore 		}
278a3477ee4SGarrett D'Amore 
279a3477ee4SGarrett D'Amore 		print_links(chip->p_vcpus);
280a3477ee4SGarrett D'Amore 		(void) putchar('\n');
281a3477ee4SGarrett D'Amore 
282a3477ee4SGarrett D'Amore 		if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
283a3477ee4SGarrett D'Amore 			if (strlen(vcpu->v_impl)) {
284a3477ee4SGarrett D'Amore 				(void) printf("  %s\n", vcpu->v_impl);
285a3477ee4SGarrett D'Amore 			}
286a3477ee4SGarrett D'Amore 			if (((len = strlen(vcpu->v_brand)) != 0) &&
287a3477ee4SGarrett D'Amore 			    (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
288a3477ee4SGarrett D'Amore 				(void) printf("\t%s", vcpu->v_brand);
289a3477ee4SGarrett D'Amore 		} else {
290a3477ee4SGarrett D'Amore 			for (l2 = chip->p_cores; l2; l2 = l2->l_next) {
291a3477ee4SGarrett D'Amore 				core = l2->l_ptr;
292a3477ee4SGarrett D'Amore 				(void) printf(_("  %s has %d virtual %s"),
293a3477ee4SGarrett D'Amore 				    _("The core"),
294a3477ee4SGarrett D'Amore 				    core->c_nvcpu,
295a3477ee4SGarrett D'Amore 				    chip->p_nvcpu > 1 ?
296a3477ee4SGarrett D'Amore 				    _("processors") : _("processor"));
297a3477ee4SGarrett D'Amore 				print_links(core->c_vcpus);
298a3477ee4SGarrett D'Amore 				(void) putchar('\n');
299a3477ee4SGarrett D'Amore 			}
300a3477ee4SGarrett D'Amore 			if (strlen(vcpu->v_impl)) {
301a3477ee4SGarrett D'Amore 				(void) printf("    %s\n", vcpu->v_impl);
302a3477ee4SGarrett D'Amore 			}
303a3477ee4SGarrett D'Amore 			if (((len = strlen(vcpu->v_brand)) != 0) &&
304a3477ee4SGarrett D'Amore 			    (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
305*db6ea8e6SKeith M Wesolowski 				(void) printf("      %s", vcpu->v_brand);
306a3477ee4SGarrett D'Amore 		}
307*db6ea8e6SKeith M Wesolowski 		if (strcmp(vcpu->v_socket, "Unknown") != 0) {
308*db6ea8e6SKeith M Wesolowski 			(void) printf("\t[ %s: %s ]", _("Socket"),
309*db6ea8e6SKeith M Wesolowski 			    vcpu->v_socket);
310*db6ea8e6SKeith M Wesolowski 		}
311*db6ea8e6SKeith M Wesolowski 		(void) putchar('\n');
312a3477ee4SGarrett D'Amore 	}
313a3477ee4SGarrett D'Amore }
314a3477ee4SGarrett D'Amore 
315a3477ee4SGarrett D'Amore static void
print_ps(void)316a3477ee4SGarrett D'Amore print_ps(void)
317a3477ee4SGarrett D'Amore {
318a3477ee4SGarrett D'Amore 	int online = 1;
319c3377ee9SJohn Levon 	struct pchip *p = NULL;
320a3477ee4SGarrett D'Amore 	struct vcpu *v;
321a3477ee4SGarrett D'Amore 	struct link *l;
322a3477ee4SGarrett D'Amore 
323a3477ee4SGarrett D'Amore 	/*
324a3477ee4SGarrett D'Amore 	 * Report "1" if all cpus colocated on the same chip are online.
325a3477ee4SGarrett D'Amore 	 */
326a3477ee4SGarrett D'Amore 	for (l = pchips; l != NULL; l = l->l_next) {
327a3477ee4SGarrett D'Amore 		p = l->l_ptr;
328a3477ee4SGarrett D'Amore 		if (p->p_doit)
329a3477ee4SGarrett D'Amore 			break;
330a3477ee4SGarrett D'Amore 	}
331a3477ee4SGarrett D'Amore 	if (p == NULL)
332a3477ee4SGarrett D'Amore 		return;	/* should never happen! */
333a3477ee4SGarrett D'Amore 	for (l = p->p_vcpus; l != NULL; l = l->l_next) {
334a3477ee4SGarrett D'Amore 		v = l->l_ptr;
335a3477ee4SGarrett D'Amore 		if (strcmp(v->v_state, "on-line") != 0) {
336a3477ee4SGarrett D'Amore 			online = 0;
337a3477ee4SGarrett D'Amore 			break;
338a3477ee4SGarrett D'Amore 		}
339a3477ee4SGarrett D'Amore 	}
340a3477ee4SGarrett D'Amore 
341a3477ee4SGarrett D'Amore 	(void) printf("%d\n", online);
342a3477ee4SGarrett D'Amore }
343a3477ee4SGarrett D'Amore 
344a3477ee4SGarrett D'Amore static void
print_s(void)345a3477ee4SGarrett D'Amore print_s(void)
346a3477ee4SGarrett D'Amore {
347a3477ee4SGarrett D'Amore 	struct link *l;
348a3477ee4SGarrett D'Amore 
349a3477ee4SGarrett D'Amore 	/*
350a3477ee4SGarrett D'Amore 	 * Find the processor (there will be only one) that we selected,
351a3477ee4SGarrett D'Amore 	 * and report whether or not it is online.
352a3477ee4SGarrett D'Amore 	 */
353a3477ee4SGarrett D'Amore 	for (l = vcpus; l != NULL; l = l->l_next) {
354a3477ee4SGarrett D'Amore 		struct vcpu *v = l->l_ptr;
355a3477ee4SGarrett D'Amore 		if (v->v_doit) {
356a3477ee4SGarrett D'Amore 			(void) printf("%d\n",
357a3477ee4SGarrett D'Amore 			    strcmp(v->v_state, "on-line") == 0 ? 1 : 0);
358a3477ee4SGarrett D'Amore 			return;
359a3477ee4SGarrett D'Amore 		}
360a3477ee4SGarrett D'Amore 	}
361a3477ee4SGarrett D'Amore }
362a3477ee4SGarrett D'Amore 
363a3477ee4SGarrett D'Amore static void
print_p(int nspec)364a3477ee4SGarrett D'Amore print_p(int nspec)
365a3477ee4SGarrett D'Amore {
366a3477ee4SGarrett D'Amore 	struct		link *l1, *l2;
367a3477ee4SGarrett D'Amore 	int		online = 0;
368a3477ee4SGarrett D'Amore 
369a3477ee4SGarrett D'Amore 	/*
370a3477ee4SGarrett D'Amore 	 * Print the number of physical packages with at least one processor
371a3477ee4SGarrett D'Amore 	 * online.
372a3477ee4SGarrett D'Amore 	 */
373a3477ee4SGarrett D'Amore 	for (l1 = pchips; l1 != NULL; l1 = l1->l_next) {
374a3477ee4SGarrett D'Amore 		struct pchip *p = l1->l_ptr;
375a3477ee4SGarrett D'Amore 		if ((nspec == 0) || (p->p_doit)) {
376a3477ee4SGarrett D'Amore 
377a3477ee4SGarrett D'Amore 			for (l2 = p->p_vcpus; l2 != NULL; l2 = l2->l_next) {
378a3477ee4SGarrett D'Amore 				struct vcpu *v = l2->l_ptr;
379a3477ee4SGarrett D'Amore 				if (strcmp(v->v_state, "on-line") == 0) {
380a3477ee4SGarrett D'Amore 					online++;
381a3477ee4SGarrett D'Amore 					break;
382a3477ee4SGarrett D'Amore 				}
383a3477ee4SGarrett D'Amore 			}
384a3477ee4SGarrett D'Amore 		}
385a3477ee4SGarrett D'Amore 	}
386a3477ee4SGarrett D'Amore 	(void) printf("%d\n", online);
387a3477ee4SGarrett D'Amore }
388a3477ee4SGarrett D'Amore 
389a3477ee4SGarrett D'Amore static void
print_v(int nspec)390a3477ee4SGarrett D'Amore print_v(int nspec)
391a3477ee4SGarrett D'Amore {
392a3477ee4SGarrett D'Amore 	struct link	*l;
393a3477ee4SGarrett D'Amore 
394a3477ee4SGarrett D'Amore 	for (l = vcpus; l != NULL; l = l->l_next) {
395a3477ee4SGarrett D'Amore 		struct vcpu *v = l->l_ptr;
396a3477ee4SGarrett D'Amore 
397a3477ee4SGarrett D'Amore 		if ((nspec != 0) && (!v->v_doit))
398a3477ee4SGarrett D'Amore 			continue;
399a3477ee4SGarrett D'Amore 		(void) printf(_("Status of virtual processor %d as of: "),
400a3477ee4SGarrett D'Amore 		    l->l_id);
401a3477ee4SGarrett D'Amore 		(void) printf("%s\n", timestr(time(NULL)));
402a3477ee4SGarrett D'Amore 		(void) printf(_("  %s since %s.\n"),
403a3477ee4SGarrett D'Amore 		    _(v->v_state), timestr(v->v_state_begin));
404a3477ee4SGarrett D'Amore 		if (v->v_clock_mhz) {
405a3477ee4SGarrett D'Amore 			(void) printf(
406a3477ee4SGarrett D'Amore 			    _("  The %s processor operates at %llu MHz,\n"),
407a3477ee4SGarrett D'Amore 			    v->v_cpu_type, (unsigned long long)v->v_clock_mhz);
408a3477ee4SGarrett D'Amore 		} else {
409a3477ee4SGarrett D'Amore 			(void) printf(
410a3477ee4SGarrett D'Amore 			    _("  The %s processor operates at " \
411a3477ee4SGarrett D'Amore 			    "an unknown frequency,\n"), v->v_cpu_type);
412a3477ee4SGarrett D'Amore 		}
413a3477ee4SGarrett D'Amore 		switch (*v->v_fpu_type) {
414a3477ee4SGarrett D'Amore 		case '\0':
415a3477ee4SGarrett D'Amore 			(void) printf(
416a3477ee4SGarrett D'Amore 			    _("\tand has no floating point processor.\n"));
417a3477ee4SGarrett D'Amore 			break;
418a3477ee4SGarrett D'Amore 		case 'a': case 'A':
419a3477ee4SGarrett D'Amore 		case 'e': case 'E':
420a3477ee4SGarrett D'Amore 		case 'i': case 'I':
421a3477ee4SGarrett D'Amore 		case 'o': case 'O':
422a3477ee4SGarrett D'Amore 		case 'u': case 'U':
423a3477ee4SGarrett D'Amore 		case 'y': case 'Y':
424a3477ee4SGarrett D'Amore 			(void) printf(
425a3477ee4SGarrett D'Amore 			    _("\tand has an %s floating point processor.\n"),
426a3477ee4SGarrett D'Amore 			    v->v_fpu_type);
427a3477ee4SGarrett D'Amore 			break;
428a3477ee4SGarrett D'Amore 		default:
429a3477ee4SGarrett D'Amore 			(void) printf(
430a3477ee4SGarrett D'Amore 			    _("\tand has a %s floating point processor.\n"),
431a3477ee4SGarrett D'Amore 			    v->v_fpu_type);
432a3477ee4SGarrett D'Amore 			break;
433a3477ee4SGarrett D'Amore 		}
434a3477ee4SGarrett D'Amore 	}
435a3477ee4SGarrett D'Amore }
436a3477ee4SGarrett D'Amore 
437a3477ee4SGarrett D'Amore static void
print_normal(int nspec)438a3477ee4SGarrett D'Amore print_normal(int nspec)
439a3477ee4SGarrett D'Amore {
440a3477ee4SGarrett D'Amore 	struct link	*l;
441a3477ee4SGarrett D'Amore 	struct vcpu	*v;
442a3477ee4SGarrett D'Amore 
443a3477ee4SGarrett D'Amore 	for (l = vcpus; l != NULL; l = l->l_next) {
444a3477ee4SGarrett D'Amore 		v = l->l_ptr;
445a3477ee4SGarrett D'Amore 		if ((nspec == 0) || (v->v_doit)) {
446a3477ee4SGarrett D'Amore 			(void) printf(_("%d\t%-8s  since %s\n"),
447a3477ee4SGarrett D'Amore 			    l->l_id, _(v->v_state), timestr(v->v_state_begin));
448a3477ee4SGarrett D'Amore 		}
449a3477ee4SGarrett D'Amore 	}
450a3477ee4SGarrett D'Amore }
451a3477ee4SGarrett D'Amore 
452c3377ee9SJohn Levon static bool
valid_propname(const char * propname)453c3377ee9SJohn Levon valid_propname(const char *propname)
454c3377ee9SJohn Levon {
455c3377ee9SJohn Levon 	size_t i;
456c3377ee9SJohn Levon 
457c3377ee9SJohn Levon 	const char *props[] = {
458c3377ee9SJohn Levon 		"smt_enabled",
459c3377ee9SJohn Levon 	};
460c3377ee9SJohn Levon 
461c3377ee9SJohn Levon 	for (i = 0; i < ARRAY_SIZE(props); i++) {
462c3377ee9SJohn Levon 		if (strcmp(propname, props[i]) == 0)
463c3377ee9SJohn Levon 			break;
464c3377ee9SJohn Levon 	}
465c3377ee9SJohn Levon 
466c3377ee9SJohn Levon 	return (i != ARRAY_SIZE(props));
467c3377ee9SJohn Levon }
468c3377ee9SJohn Levon 
469c3377ee9SJohn Levon static void
read_property(const char * propname)470c3377ee9SJohn Levon read_property(const char *propname)
471c3377ee9SJohn Levon {
472c3377ee9SJohn Levon 	di_prop_t prop = DI_PROP_NIL;
473c3377ee9SJohn Levon 	di_node_t root_node;
474c3377ee9SJohn Levon 	bool show_all = strcmp(propname, "all") == 0;
475c3377ee9SJohn Levon 
476c3377ee9SJohn Levon 	if (!show_all && !valid_propname(propname))
477c3377ee9SJohn Levon 		errx(EXIT_FAILURE, _("unknown CPU property %s"), propname);
478c3377ee9SJohn Levon 
479c3377ee9SJohn Levon 	if ((root_node = di_init("/", DINFOPROP)) == NULL)
480c3377ee9SJohn Levon 		err(EXIT_FAILURE, _("failed to read root node"));
481c3377ee9SJohn Levon 
482c3377ee9SJohn Levon 	while ((prop = di_prop_sys_next(root_node, prop)) != DI_PROP_NIL) {
483c3377ee9SJohn Levon 		const char *name = di_prop_name(prop);
484c3377ee9SJohn Levon 		char *val;
485c3377ee9SJohn Levon 		int nr_vals;
486c3377ee9SJohn Levon 
487c3377ee9SJohn Levon 		if (!valid_propname(name))
488c3377ee9SJohn Levon 			continue;
489c3377ee9SJohn Levon 
490c3377ee9SJohn Levon 		if (!show_all && strcmp(di_prop_name(prop), propname) != 0)
491c3377ee9SJohn Levon 			continue;
492c3377ee9SJohn Levon 
493c3377ee9SJohn Levon 		if ((nr_vals = di_prop_strings(prop, &val)) < 1) {
494c3377ee9SJohn Levon 			err(EXIT_FAILURE,
495c3377ee9SJohn Levon 			    _("error reading property %s"), name);
496c3377ee9SJohn Levon 		} else if (nr_vals != 1) {
497c3377ee9SJohn Levon 			errx(EXIT_FAILURE, _("invalid property %s"), name);
498c3377ee9SJohn Levon 		}
499c3377ee9SJohn Levon 
500c3377ee9SJohn Levon 		printf("%s=%s\n", name, val);
501c3377ee9SJohn Levon 
502c3377ee9SJohn Levon 		if (!show_all)
503c3377ee9SJohn Levon 			exit(EXIT_SUCCESS);
504c3377ee9SJohn Levon 	}
505c3377ee9SJohn Levon 
506c3377ee9SJohn Levon 	if (!show_all)
507c3377ee9SJohn Levon 		errx(EXIT_FAILURE, _("property %s was not found"), propname);
508c3377ee9SJohn Levon 
509c3377ee9SJohn Levon 	di_fini(root_node);
510c3377ee9SJohn Levon }
511c3377ee9SJohn Levon 
512c3377ee9SJohn Levon static void
print_total(int opt_c,int opt_p,const char * opt_S)513c3377ee9SJohn Levon print_total(int opt_c, int opt_p, const char *opt_S)
514c3377ee9SJohn Levon {
515c3377ee9SJohn Levon 	uint_t count = 0;
516c3377ee9SJohn Levon 
517c3377ee9SJohn Levon 	if (opt_c) {
518c3377ee9SJohn Levon 		printf("%u\n", nr_cores);
519c3377ee9SJohn Levon 		return;
520c3377ee9SJohn Levon 	} else if (opt_p) {
521c3377ee9SJohn Levon 		printf("%u\n", nr_chips);
522c3377ee9SJohn Levon 		return;
523c3377ee9SJohn Levon 	} else if (opt_S == NULL || strcmp(opt_S, "all") == 0) {
524c3377ee9SJohn Levon 		printf("%u\n", nr_cpus);
525c3377ee9SJohn Levon 		return;
526c3377ee9SJohn Levon 	}
527c3377ee9SJohn Levon 
528c3377ee9SJohn Levon 
529c3377ee9SJohn Levon 	for (struct link *l = vcpus; l != NULL; l = l->l_next) {
530c3377ee9SJohn Levon 		struct vcpu *v = l->l_ptr;
531c3377ee9SJohn Levon 		if (strcmp(opt_S, v->v_state) == 0)
532c3377ee9SJohn Levon 			count++;
533c3377ee9SJohn Levon 	}
534c3377ee9SJohn Levon 
535c3377ee9SJohn Levon 	printf("%u\n", count);
536c3377ee9SJohn Levon }
537c3377ee9SJohn Levon 
538a3477ee4SGarrett D'Amore int
main(int argc,char ** argv)539a3477ee4SGarrett D'Amore main(int argc, char **argv)
540a3477ee4SGarrett D'Amore {
541a3477ee4SGarrett D'Amore 	kstat_ctl_t	*kc;
542a3477ee4SGarrett D'Amore 	kstat_t		*ksp;
543a3477ee4SGarrett D'Amore 	kstat_named_t	*knp;
544a3477ee4SGarrett D'Amore 	struct vcpu	*vc;
545a3477ee4SGarrett D'Amore 	struct core	*core;
546a3477ee4SGarrett D'Amore 	struct pchip	*chip;
547a3477ee4SGarrett D'Amore 	struct link	**ins;
548a3477ee4SGarrett D'Amore 	char		*s;
549a3477ee4SGarrett D'Amore 	int		nspec;
550a3477ee4SGarrett D'Amore 	int		optc;
551c3377ee9SJohn Levon 	int		opt_c = 0;
552a3477ee4SGarrett D'Amore 	int		opt_p = 0;
553c3377ee9SJohn Levon 	const char	*opt_r = NULL;
554c3377ee9SJohn Levon 	const char	*opt_S = NULL;
555c3377ee9SJohn Levon 	int		opt_s = 0;
556c3377ee9SJohn Levon 	int		opt_t = 0;
557a3477ee4SGarrett D'Amore 	int		opt_v = 0;
558a3477ee4SGarrett D'Amore 	int		ex = 0;
559a3477ee4SGarrett D'Amore 
560a3477ee4SGarrett D'Amore 	cmdname = basename(argv[0]);
561a3477ee4SGarrett D'Amore 
562a3477ee4SGarrett D'Amore 
563a3477ee4SGarrett D'Amore 	(void) setlocale(LC_ALL, "");
564a3477ee4SGarrett D'Amore #if !defined(TEXT_DOMAIN)
565a3477ee4SGarrett D'Amore #define	TEXT_DOMAIN	"SYS_TEST"
566a3477ee4SGarrett D'Amore #endif
567a3477ee4SGarrett D'Amore 	(void) textdomain(TEXT_DOMAIN);
568a3477ee4SGarrett D'Amore 
569a3477ee4SGarrett D'Amore 	/* collect the kstats */
570a3477ee4SGarrett D'Amore 	if ((kc = kstat_open()) == NULL)
571a3477ee4SGarrett D'Amore 		die(_("kstat_open() failed"));
572a3477ee4SGarrett D'Amore 
573a3477ee4SGarrett D'Amore 	if ((ksp = kstat_lookup(kc, "cpu_info", -1, NULL)) == NULL)
574a3477ee4SGarrett D'Amore 		die(_("kstat_lookup() failed"));
575a3477ee4SGarrett D'Amore 
576a3477ee4SGarrett D'Amore 	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
577a3477ee4SGarrett D'Amore 
578a3477ee4SGarrett D'Amore 		if (strcmp(ksp->ks_module, "cpu_info") != 0)
579a3477ee4SGarrett D'Amore 			continue;
580554bfeedSToomas Soome 		if (kstat_read(kc, ksp, NULL) == -1)
581a3477ee4SGarrett D'Amore 			die(_("kstat_read() failed"));
582a3477ee4SGarrett D'Amore 
583a3477ee4SGarrett D'Amore 		vc = find_link(&vcpus, ksp->ks_instance, &ins);
584a3477ee4SGarrett D'Amore 		if (vc == NULL) {
585a3477ee4SGarrett D'Amore 			vc = zalloc(sizeof (struct vcpu));
586a3477ee4SGarrett D'Amore 			vc->v_link.l_id = ksp->ks_instance;
587a3477ee4SGarrett D'Amore 			vc->v_link_core.l_id = ksp->ks_instance;
588a3477ee4SGarrett D'Amore 			vc->v_link_pchip.l_id = ksp->ks_instance;
589a3477ee4SGarrett D'Amore 			vc->v_link.l_ptr = vc;
590a3477ee4SGarrett D'Amore 			vc->v_link_core.l_ptr = vc;
591a3477ee4SGarrett D'Amore 			vc->v_link_pchip.l_ptr = vc;
592a3477ee4SGarrett D'Amore 			ins_link(ins, &vc->v_link);
593c3377ee9SJohn Levon 			nr_cpus++;
594a3477ee4SGarrett D'Amore 		}
595a3477ee4SGarrett D'Amore 
596a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "state")) != NULL) {
597a3477ee4SGarrett D'Amore 			vc->v_state = mystrdup(knp->value.c);
598a3477ee4SGarrett D'Amore 		} else {
599a3477ee4SGarrett D'Amore 			vc->v_state = "unknown";
600a3477ee4SGarrett D'Amore 		}
601a3477ee4SGarrett D'Amore 
602a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "cpu_type")) != NULL) {
603a3477ee4SGarrett D'Amore 			vc->v_cpu_type = mystrdup(knp->value.c);
604a3477ee4SGarrett D'Amore 		}
605a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "fpu_type")) != NULL) {
606a3477ee4SGarrett D'Amore 			vc->v_fpu_type = mystrdup(knp->value.c);
607a3477ee4SGarrett D'Amore 		}
608a3477ee4SGarrett D'Amore 
609a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "state_begin")) != NULL) {
610a3477ee4SGarrett D'Amore 			vc->v_state_begin = knp->value.l;
611a3477ee4SGarrett D'Amore 		}
612a3477ee4SGarrett D'Amore 
613a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "clock_MHz")) != NULL) {
614a3477ee4SGarrett D'Amore 			vc->v_clock_mhz = knp->value.l;
615a3477ee4SGarrett D'Amore 		}
616a3477ee4SGarrett D'Amore 
617a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "brand")) == NULL) {
618a3477ee4SGarrett D'Amore 			vc->v_brand = _("(unknown)");
619a3477ee4SGarrett D'Amore 		} else {
620a3477ee4SGarrett D'Amore 			vc->v_brand = mystrdup(knp->value.str.addr.ptr);
621a3477ee4SGarrett D'Amore 		}
622a3477ee4SGarrett D'Amore 
62348ac0edbSHans Rosenfeld 		if ((knp = kstat_data_lookup(ksp, "socket_type")) == NULL) {
62448ac0edbSHans Rosenfeld 			vc->v_socket = "Unknown";
62548ac0edbSHans Rosenfeld 		} else {
62648ac0edbSHans Rosenfeld 			vc->v_socket = mystrdup(knp->value.str.addr.ptr);
62748ac0edbSHans Rosenfeld 		}
62848ac0edbSHans Rosenfeld 
629a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "implementation")) == NULL) {
630a3477ee4SGarrett D'Amore 			vc->v_impl = _("(unknown)");
631a3477ee4SGarrett D'Amore 		} else {
632a3477ee4SGarrett D'Amore 			vc->v_impl = mystrdup(knp->value.str.addr.ptr);
633a3477ee4SGarrett D'Amore 		}
634a3477ee4SGarrett D'Amore 		/*
635a3477ee4SGarrett D'Amore 		 * Legacy code removed the chipid and cpuid fields... we
636a3477ee4SGarrett D'Amore 		 * do the same for compatibility.  Note that the original
637a3477ee4SGarrett D'Amore 		 * pattern is a bit strange, and we have to emulate this because
638a3477ee4SGarrett D'Amore 		 * on SPARC we *do* emit these.  The original pattern we are
639a3477ee4SGarrett D'Amore 		 * emulating is: $impl =~ s/(cpuid|chipid)\s*\w+\s+//;
640a3477ee4SGarrett D'Amore 		 */
641a3477ee4SGarrett D'Amore 		if ((s = strstr(vc->v_impl, "chipid")) != NULL) {
642a3477ee4SGarrett D'Amore 			char *x = s + strlen("chipid");
643a3477ee4SGarrett D'Amore 			while (isspace(*x))
644a3477ee4SGarrett D'Amore 				x++;
645a3477ee4SGarrett D'Amore 			if ((!isalnum(*x)) && (*x != '_'))
646a3477ee4SGarrett D'Amore 				goto nochipid;
647a3477ee4SGarrett D'Amore 			while (isalnum(*x) || (*x == '_'))
648a3477ee4SGarrett D'Amore 				x++;
649a3477ee4SGarrett D'Amore 			if (!isspace(*x))
650a3477ee4SGarrett D'Amore 				goto nochipid;
651a3477ee4SGarrett D'Amore 			while (isspace(*x))
652a3477ee4SGarrett D'Amore 				x++;
653a3477ee4SGarrett D'Amore 			(void) strcpy(s, x);
654a3477ee4SGarrett D'Amore 		}
655a3477ee4SGarrett D'Amore nochipid:
656a3477ee4SGarrett D'Amore 		if ((s = strstr(vc->v_impl, "cpuid")) != NULL) {
657a3477ee4SGarrett D'Amore 			char *x = s + strlen("cpuid");
658a3477ee4SGarrett D'Amore 			while (isspace(*x))
659a3477ee4SGarrett D'Amore 				x++;
660a3477ee4SGarrett D'Amore 			if ((!isalnum(*x)) && (*x != '_'))
661a3477ee4SGarrett D'Amore 				goto nocpuid;
662a3477ee4SGarrett D'Amore 			while (isalnum(*x) || (*x == '_'))
663a3477ee4SGarrett D'Amore 				x++;
664a3477ee4SGarrett D'Amore 			if (!isspace(*x))
665a3477ee4SGarrett D'Amore 				goto nocpuid;
666a3477ee4SGarrett D'Amore 			while (isspace(*x))
667a3477ee4SGarrett D'Amore 				x++;
668a3477ee4SGarrett D'Amore 			(void) strcpy(s, x);
669a3477ee4SGarrett D'Amore 		}
670a3477ee4SGarrett D'Amore nocpuid:
671a3477ee4SGarrett D'Amore 
672a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "chip_id")) != NULL)
673a3477ee4SGarrett D'Amore 			vc->v_pchip_id = knp->value.l;
674a3477ee4SGarrett D'Amore 		chip = find_link(&pchips, vc->v_pchip_id, &ins);
675a3477ee4SGarrett D'Amore 		if (chip == NULL) {
676a3477ee4SGarrett D'Amore 			chip = zalloc(sizeof (struct pchip));
677a3477ee4SGarrett D'Amore 			chip->p_link.l_id = vc->v_pchip_id;
678a3477ee4SGarrett D'Amore 			chip->p_link.l_ptr = chip;
679a3477ee4SGarrett D'Amore 			ins_link(ins, &chip->p_link);
680c3377ee9SJohn Levon 			nr_chips++;
681a3477ee4SGarrett D'Amore 		}
682a3477ee4SGarrett D'Amore 		vc->v_pchip = chip;
683a3477ee4SGarrett D'Amore 
684a3477ee4SGarrett D'Amore 		if ((knp = kstat_data_lookup(ksp, "core_id")) != NULL)
685a3477ee4SGarrett D'Amore 			vc->v_core_id = knp->value.l;
686a3477ee4SGarrett D'Amore 		core = find_link(&cores, vc->v_core_id, &ins);
687a3477ee4SGarrett D'Amore 		if (core == NULL) {
688a3477ee4SGarrett D'Amore 			core = zalloc(sizeof (struct core));
689a3477ee4SGarrett D'Amore 			core->c_link.l_id = vc->v_core_id;
690a3477ee4SGarrett D'Amore 			core->c_link.l_ptr = core;
691a3477ee4SGarrett D'Amore 			core->c_link_pchip.l_id = vc->v_core_id;
692a3477ee4SGarrett D'Amore 			core->c_link_pchip.l_ptr = core;
693a3477ee4SGarrett D'Amore 			core->c_pchip = chip;
694a3477ee4SGarrett D'Amore 			ins_link(ins, &core->c_link);
695a3477ee4SGarrett D'Amore 			chip->p_ncore++;
696a3477ee4SGarrett D'Amore 			(void) find_link(&chip->p_cores, core->c_link.l_id,
697a3477ee4SGarrett D'Amore 			    &ins);
698a3477ee4SGarrett D'Amore 			ins_link(ins, &core->c_link_pchip);
699c3377ee9SJohn Levon 			nr_cores++;
700a3477ee4SGarrett D'Amore 		}
701a3477ee4SGarrett D'Amore 		vc->v_core = core;
702a3477ee4SGarrett D'Amore 
703a3477ee4SGarrett D'Amore 
704a3477ee4SGarrett D'Amore 
705a3477ee4SGarrett D'Amore 		/* now put other linkages in place */
706a3477ee4SGarrett D'Amore 		(void) find_link(&chip->p_vcpus, vc->v_link.l_id, &ins);
707a3477ee4SGarrett D'Amore 		ins_link(ins, &vc->v_link_pchip);
708a3477ee4SGarrett D'Amore 		chip->p_nvcpu++;
709a3477ee4SGarrett D'Amore 
710a3477ee4SGarrett D'Amore 		(void) find_link(&core->c_vcpus, vc->v_link.l_id, &ins);
711a3477ee4SGarrett D'Amore 		ins_link(ins, &vc->v_link_core);
712a3477ee4SGarrett D'Amore 		core->c_nvcpu++;
713a3477ee4SGarrett D'Amore 	}
714a3477ee4SGarrett D'Amore 
715a3477ee4SGarrett D'Amore 	(void) kstat_close(kc);
716a3477ee4SGarrett D'Amore 
717a3477ee4SGarrett D'Amore 	nspec = 0;
718a3477ee4SGarrett D'Amore 
719c3377ee9SJohn Levon 	while ((optc = getopt(argc, argv, "cpr:S:stv")) != EOF) {
720a3477ee4SGarrett D'Amore 		switch (optc) {
721c3377ee9SJohn Levon 		case 'c':
722c3377ee9SJohn Levon 			opt_c = 1;
723a3477ee4SGarrett D'Amore 			break;
724a3477ee4SGarrett D'Amore 		case 'p':
725a3477ee4SGarrett D'Amore 			opt_p = 1;
726a3477ee4SGarrett D'Amore 			break;
727c3377ee9SJohn Levon 		case 'r':
728c3377ee9SJohn Levon 			opt_r = optarg;
729c3377ee9SJohn Levon 			break;
730c3377ee9SJohn Levon 		case 'S':
731c3377ee9SJohn Levon 			opt_S = optarg;
732c3377ee9SJohn Levon 			break;
733c3377ee9SJohn Levon 		case 's':
734c3377ee9SJohn Levon 			opt_s = 1;
735c3377ee9SJohn Levon 			break;
736c3377ee9SJohn Levon 		case 't':
737c3377ee9SJohn Levon 			opt_t = 1;
738c3377ee9SJohn Levon 			break;
739a3477ee4SGarrett D'Amore 		case 'v':
740a3477ee4SGarrett D'Amore 			opt_v = 1;
741a3477ee4SGarrett D'Amore 			break;
742a3477ee4SGarrett D'Amore 		default:
743a3477ee4SGarrett D'Amore 			usage(NULL);
744a3477ee4SGarrett D'Amore 		}
745a3477ee4SGarrett D'Amore 	}
746a3477ee4SGarrett D'Amore 
747c3377ee9SJohn Levon 	if (opt_r != NULL) {
748c3377ee9SJohn Levon 		if (optind != argc)
749c3377ee9SJohn Levon 			usage(_("cannot specify CPUs with -r"));
750c3377ee9SJohn Levon 		if (opt_c || opt_p || opt_S != NULL || opt_s || opt_t || opt_v)
751c3377ee9SJohn Levon 			usage(_("cannot specify other arguments with -r"));
752c3377ee9SJohn Levon 
753c3377ee9SJohn Levon 		read_property(opt_r);
754c3377ee9SJohn Levon 		return (EXIT_SUCCESS);
755c3377ee9SJohn Levon 	}
756c3377ee9SJohn Levon 
7571b55eab7SToomas Soome 	if (opt_t != 0) {
758c3377ee9SJohn Levon 		if (optind != argc)
759c3377ee9SJohn Levon 			usage(_("cannot specify CPUs with -t"));
760c3377ee9SJohn Levon 		if (opt_s || opt_v)
761c3377ee9SJohn Levon 			usage(_("cannot specify -s or -v with -t"));
762c3377ee9SJohn Levon 		if (opt_S != NULL && (opt_c || opt_p))
763c3377ee9SJohn Levon 			usage(_("cannot specify CPU state with -c or -p"));
764c3377ee9SJohn Levon 		if (opt_c && opt_p)
765c3377ee9SJohn Levon 			usage(_("cannot specify -c and -p"));
766c3377ee9SJohn Levon 
767c3377ee9SJohn Levon 		print_total(opt_c, opt_p, opt_S);
768c3377ee9SJohn Levon 		return (EXIT_SUCCESS);
769c3377ee9SJohn Levon 	}
770c3377ee9SJohn Levon 
771c3377ee9SJohn Levon 	if (opt_S != NULL || opt_c)
772c3377ee9SJohn Levon 		usage(_("cannot specify -S or -c without -t"));
773c3377ee9SJohn Levon 
774a3477ee4SGarrett D'Amore 	while (optind < argc) {
775a3477ee4SGarrett D'Amore 		long id;
776a3477ee4SGarrett D'Amore 		char *eptr;
777a3477ee4SGarrett D'Amore 		struct link *l;
778a3477ee4SGarrett D'Amore 		id = strtol(argv[optind], &eptr, 10);
779a3477ee4SGarrett D'Amore 		l = find_link(&vcpus, id, NULL);
780a3477ee4SGarrett D'Amore 		if ((*eptr != '\0') || (l == NULL)) {
781a3477ee4SGarrett D'Amore 			(void) fprintf(stderr,
782a3477ee4SGarrett D'Amore 			    _("%s: processor %s: Invalid argument\n"),
783a3477ee4SGarrett D'Amore 			    cmdname, argv[optind]);
784a3477ee4SGarrett D'Amore 			ex = 2;
785a3477ee4SGarrett D'Amore 		} else {
786a3477ee4SGarrett D'Amore 			((struct vcpu *)l->l_ptr)->v_doit = 1;
787a3477ee4SGarrett D'Amore 			((struct vcpu *)l->l_ptr)->v_pchip->p_doit = 1;
788a3477ee4SGarrett D'Amore 			((struct vcpu *)l->l_ptr)->v_core->c_doit = 1;
789a3477ee4SGarrett D'Amore 		}
790a3477ee4SGarrett D'Amore 		nspec++;
791a3477ee4SGarrett D'Amore 		optind++;
792a3477ee4SGarrett D'Amore 	}
793a3477ee4SGarrett D'Amore 
794a3477ee4SGarrett D'Amore 	if (opt_s && opt_v) {
795a3477ee4SGarrett D'Amore 		usage(_("options -s and -v are mutually exclusive"));
796a3477ee4SGarrett D'Amore 	}
797a3477ee4SGarrett D'Amore 	if (opt_s && nspec != 1) {
798a3477ee4SGarrett D'Amore 		usage(_("must specify exactly one processor if -s used"));
799a3477ee4SGarrett D'Amore 	}
800a3477ee4SGarrett D'Amore 	if (opt_v && opt_p) {
801a3477ee4SGarrett D'Amore 		print_vp(nspec);
802a3477ee4SGarrett D'Amore 	} else if (opt_s && opt_p) {
803a3477ee4SGarrett D'Amore 		print_ps();
804a3477ee4SGarrett D'Amore 	} else if (opt_p) {
805a3477ee4SGarrett D'Amore 		print_p(nspec);
806a3477ee4SGarrett D'Amore 	} else if (opt_v) {
807a3477ee4SGarrett D'Amore 		print_v(nspec);
808a3477ee4SGarrett D'Amore 	} else if (opt_s) {
809a3477ee4SGarrett D'Amore 		print_s();
810a3477ee4SGarrett D'Amore 	} else {
811a3477ee4SGarrett D'Amore 		print_normal(nspec);
812a3477ee4SGarrett D'Amore 	}
813a3477ee4SGarrett D'Amore 
814a3477ee4SGarrett D'Amore 	return (ex);
815a3477ee4SGarrett D'Amore }
816