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