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 2008 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
get_cpu_freq(Prom_node * pnode)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
get_ecache_size(Prom_node * node)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
display_cpu_devices(Sys_tree * tree)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
display_cpus(Board_node * board)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 uint_t 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(" %3u ", 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
display_mid(int mid)242 display_mid(int mid)
243 {
244 log_printf(" %2d ", mid, 0);
245 }
246