xref: /illumos-gate/usr/src/lib/libprtdiag/common/cpu.c (revision 10a4fa49f51ed9ae1c857a626de6ce9ebf41661a)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <kvm.h>
33 #include <varargs.h>
34 #include <errno.h>
35 #include <time.h>
36 #include <dirent.h>
37 #include <fcntl.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/utsname.h>
42 #include <sys/openpromio.h>
43 #include <sys/spitregs.h>
44 #include <sys/cheetahregs.h>
45 #include <kstat.h>
46 #include <libintl.h>
47 #include <syslog.h>
48 #include <sys/dkio.h>
49 #include "pdevinfo.h"
50 #include "display.h"
51 #include "pdevinfo_sun4u.h"
52 #include "display_sun4u.h"
53 #include "libprtdiag.h"
54 
55 /*
56  * Return the operating frequency of a processor in Hertz. This function
57  * requires as input a legal prom node pointer. If a NULL
58  * is passed in or the clock-frequency property does not exist, the
59  * function returns 0.
60  */
61 uint_t
62 get_cpu_freq(Prom_node *pnode)
63 {
64 	Prop *prop;
65 	uint_t *value;
66 
67 	/* find the property */
68 	if ((prop = find_prop(pnode, "clock-frequency")) == NULL) {
69 		return (0);
70 	}
71 
72 	if ((value = (uint_t *)get_prop_val(prop)) == NULL) {
73 		return (0);
74 	}
75 
76 	return (*value);
77 }
78 
79 /*
80  * returns the size of the given processors external cache in
81  * bytes. If the properties required to determine this are not
82  * present, then the function returns 0.
83  */
84 int
85 get_ecache_size(Prom_node *node)
86 {
87 	int *cache_size_p;	/* pointer to number of cache lines */
88 
89 	/* find the properties */
90 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
91 		"ecache-size"))) {
92 		return (*cache_size_p);
93 	}
94 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
95 		"l3-cache-size"))) {
96 		return (*cache_size_p);
97 	}
98 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
99 		"l2-cache-size"))) {
100 		return (*cache_size_p);
101 	}
102 
103 	return (0);
104 }
105 
106 
107 /*
108  * This routine is the generic link into displaying CPU and memory info.
109  * It displays the table header, then calls the CPU and memory display
110  * routine for all boards.
111  */
112 void
113 display_cpu_devices(Sys_tree *tree)
114 {
115 	Board_node *bnode;
116 
117 	/*
118 	 * Display the table header for CPUs . Then display the CPU
119 	 * frequency, cache size, and processor revision of all cpus.
120 	 */
121 	log_printf("\n", 0);
122 	log_printf("=========================", 0);
123 	log_printf(" CPUs ", 0);
124 	log_printf("=========================", 0);
125 	log_printf("\n", 0);
126 	log_printf("\n", 0);
127 	log_printf("                    Run   Ecache  "
128 		" CPU    CPU\n", 0);
129 	log_printf("Brd  CPU   Module   MHz     MB    "
130 		"Impl.   Mask\n", 0);
131 	log_printf("---  ---  -------  -----  ------  "
132 		"------  ----\n", 0);
133 
134 	/* Now display all of the cpus on each board */
135 	bnode = tree->bd_list;
136 	while (bnode != NULL) {
137 		display_cpus(bnode);
138 	bnode = bnode->next;
139 	}
140 
141 	log_printf("\n", 0);
142 }
143 
144 /*
145  * Display the CPUs present on this board.
146  */
147 void
148 display_cpus(Board_node *board)
149 {
150 	Prom_node *cpu;
151 
152 	/*
153 	 * display the CPUs' operating frequency, cache size, impl. field
154 	 * and mask revision.
155 	 */
156 	for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
157 	    cpu = dev_next_type(cpu, "cpu")) {
158 		int freq;	 /* CPU clock frequency */
159 		int ecache_size; /* External cache size */
160 		int *mid;
161 		int *impl;
162 		int *mask, decoded_mask;
163 
164 		mid = (int *)get_prop_val(find_prop(cpu, "upa-portid"));
165 		if (mid == NULL) {
166 			mid = (int *)get_prop_val(find_prop(cpu, "portid"));
167 		}
168 
169 		freq = (get_cpu_freq(cpu) + 500000) / 1000000;
170 		ecache_size = get_ecache_size(cpu);
171 		impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
172 		mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
173 
174 		/* Do not display a failed CPU node */
175 		if ((freq != 0) && (node_failed(cpu) == 0)) {
176 			/* Board number */
177 			display_boardnum(board->board_num);
178 
179 			/* CPU MID */
180 			log_printf(" %2d  ", *mid, 0);
181 
182 			/* Module number */
183 			display_mid(*mid);
184 
185 			/* Running frequency */
186 			log_printf(" %3d   ", freq, 0);
187 
188 			/* Ecache size */
189 			if (ecache_size == 0)
190 				log_printf(" %3s    ", "N/A", 0);
191 			else
192 				log_printf(" %4.1f   ",
193 					(float)ecache_size / (float)(1<<20),
194 					0);
195 
196 			/* Implementation */
197 			if (impl == NULL) {
198 				log_printf("%6s  ", "N/A", 0);
199 			} else {
200 				switch (*impl) {
201 				case SPITFIRE_IMPL:
202 					log_printf("%-6s  ", "US-I", 0);
203 					break;
204 				case BLACKBIRD_IMPL:
205 					log_printf("%-6s  ", "US-II", 0);
206 					break;
207 				case CHEETAH_IMPL:
208 					log_printf("%-6s  ", "US-III", 0);
209 					break;
210 				case CHEETAH_PLUS_IMPL:
211 					log_printf("%-7s  ", "US-III+", 0);
212 					break;
213 				case JAGUAR_IMPL:
214 					log_printf("%-6s  ", "US-IV", 0);
215 					break;
216 				default:
217 					log_printf("%-6x  ", *impl, 0);
218 					break;
219 				}
220 			}
221 
222 			/* CPU Mask */
223 			if (mask == NULL) {
224 				log_printf(" %3s", "N/A", 0);
225 			} else {
226 				if ((impl) && IS_CHEETAH(*impl))
227 					decoded_mask =
228 						REMAP_CHEETAH_MASK(*mask);
229 				else
230 					decoded_mask = *mask;
231 
232 				log_printf(" %d.%d", (decoded_mask >> 4) & 0xf,
233 					decoded_mask & 0xf, 0);
234 			}
235 
236 			log_printf("\n", 0);
237 		}
238 	}
239 }
240 
241 void
242 display_mid(int mid)
243 {
244 	log_printf("  %2d     ", mid, 0);
245 }
246