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