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