xref: /onnv-gate/usr/src/lib/libprtdiag/common/cpu.c (revision 5889:686e556a6c1d)
11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
71708Sstevel  *
81708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel  * or http://www.opensolaris.org/os/licensing.
101708Sstevel  * See the License for the specific language governing permissions
111708Sstevel  * and limitations under the License.
121708Sstevel  *
131708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel  *
191708Sstevel  * CDDL HEADER END
201708Sstevel  */
211708Sstevel /*
22*5889Szk194757  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
231708Sstevel  * Use is subject to license terms.
241708Sstevel  */
251708Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
261708Sstevel 
271708Sstevel #include <stdio.h>
281708Sstevel #include <stdlib.h>
291708Sstevel #include <unistd.h>
301708Sstevel #include <ctype.h>
311708Sstevel #include <string.h>
321708Sstevel #include <kvm.h>
331708Sstevel #include <varargs.h>
341708Sstevel #include <errno.h>
351708Sstevel #include <time.h>
361708Sstevel #include <dirent.h>
371708Sstevel #include <fcntl.h>
381708Sstevel #include <sys/param.h>
391708Sstevel #include <sys/stat.h>
401708Sstevel #include <sys/types.h>
411708Sstevel #include <sys/utsname.h>
421708Sstevel #include <sys/openpromio.h>
431708Sstevel #include <sys/spitregs.h>
441708Sstevel #include <sys/cheetahregs.h>
451708Sstevel #include <kstat.h>
461708Sstevel #include <libintl.h>
471708Sstevel #include <syslog.h>
481708Sstevel #include <sys/dkio.h>
491708Sstevel #include "pdevinfo.h"
501708Sstevel #include "display.h"
511708Sstevel #include "pdevinfo_sun4u.h"
521708Sstevel #include "display_sun4u.h"
531708Sstevel #include "libprtdiag.h"
541708Sstevel 
551708Sstevel /*
561708Sstevel  * Return the operating frequency of a processor in Hertz. This function
571708Sstevel  * requires as input a legal prom node pointer. If a NULL
581708Sstevel  * is passed in or the clock-frequency property does not exist, the
591708Sstevel  * function returns 0.
601708Sstevel  */
611772Sjl139090 uint_t
get_cpu_freq(Prom_node * pnode)621708Sstevel get_cpu_freq(Prom_node *pnode)
631708Sstevel {
641708Sstevel 	Prop *prop;
651772Sjl139090 	uint_t *value;
661708Sstevel 
671708Sstevel 	/* find the property */
681708Sstevel 	if ((prop = find_prop(pnode, "clock-frequency")) == NULL) {
691708Sstevel 		return (0);
701708Sstevel 	}
711708Sstevel 
721772Sjl139090 	if ((value = (uint_t *)get_prop_val(prop)) == NULL) {
731708Sstevel 		return (0);
741708Sstevel 	}
751708Sstevel 
761708Sstevel 	return (*value);
771708Sstevel }
781708Sstevel 
791708Sstevel /*
801708Sstevel  * returns the size of the given processors external cache in
811708Sstevel  * bytes. If the properties required to determine this are not
821708Sstevel  * present, then the function returns 0.
831708Sstevel  */
841708Sstevel int
get_ecache_size(Prom_node * node)851708Sstevel get_ecache_size(Prom_node *node)
861708Sstevel {
871708Sstevel 	int *cache_size_p;	/* pointer to number of cache lines */
881708Sstevel 
891708Sstevel 	/* find the properties */
901708Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
91*5889Szk194757 	    "ecache-size"))) {
921708Sstevel 		return (*cache_size_p);
931708Sstevel 	}
941708Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
95*5889Szk194757 	    "l3-cache-size"))) {
961708Sstevel 		return (*cache_size_p);
971708Sstevel 	}
981708Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
99*5889Szk194757 	    "l2-cache-size"))) {
1001708Sstevel 		return (*cache_size_p);
1011708Sstevel 	}
1021708Sstevel 
1031708Sstevel 	return (0);
1041708Sstevel }
1051708Sstevel 
1061708Sstevel 
1071708Sstevel /*
1081708Sstevel  * This routine is the generic link into displaying CPU and memory info.
1091708Sstevel  * It displays the table header, then calls the CPU and memory display
1101708Sstevel  * routine for all boards.
1111708Sstevel  */
1121708Sstevel void
display_cpu_devices(Sys_tree * tree)1131708Sstevel display_cpu_devices(Sys_tree *tree)
1141708Sstevel {
1151708Sstevel 	Board_node *bnode;
1161708Sstevel 
1171708Sstevel 	/*
1181708Sstevel 	 * Display the table header for CPUs . Then display the CPU
1191708Sstevel 	 * frequency, cache size, and processor revision of all cpus.
1201708Sstevel 	 */
1211708Sstevel 	log_printf("\n", 0);
1221708Sstevel 	log_printf("=========================", 0);
1231708Sstevel 	log_printf(" CPUs ", 0);
1241708Sstevel 	log_printf("=========================", 0);
1251708Sstevel 	log_printf("\n", 0);
1261708Sstevel 	log_printf("\n", 0);
1271708Sstevel 	log_printf("                    Run   Ecache  "
128*5889Szk194757 	    " CPU    CPU\n", 0);
1291708Sstevel 	log_printf("Brd  CPU   Module   MHz     MB    "
130*5889Szk194757 	    "Impl.   Mask\n", 0);
1311708Sstevel 	log_printf("---  ---  -------  -----  ------  "
132*5889Szk194757 	    "------  ----\n", 0);
1331708Sstevel 
1341708Sstevel 	/* Now display all of the cpus on each board */
1351708Sstevel 	bnode = tree->bd_list;
1361708Sstevel 	while (bnode != NULL) {
1371708Sstevel 		display_cpus(bnode);
1381708Sstevel 	bnode = bnode->next;
1391708Sstevel 	}
1401708Sstevel 
1411708Sstevel 	log_printf("\n", 0);
1421708Sstevel }
1431708Sstevel 
1441708Sstevel /*
1451708Sstevel  * Display the CPUs present on this board.
1461708Sstevel  */
1471708Sstevel void
display_cpus(Board_node * board)1481708Sstevel display_cpus(Board_node *board)
1491708Sstevel {
1501708Sstevel 	Prom_node *cpu;
1511708Sstevel 
1521708Sstevel 	/*
1531708Sstevel 	 * display the CPUs' operating frequency, cache size, impl. field
1541708Sstevel 	 * and mask revision.
1551708Sstevel 	 */
1561708Sstevel 	for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
1571708Sstevel 	    cpu = dev_next_type(cpu, "cpu")) {
158*5889Szk194757 		uint_t freq;	 /* CPU clock frequency */
1591708Sstevel 		int ecache_size; /* External cache size */
1601708Sstevel 		int *mid;
1611708Sstevel 		int *impl;
1621708Sstevel 		int *mask, decoded_mask;
1631708Sstevel 
1641708Sstevel 		mid = (int *)get_prop_val(find_prop(cpu, "upa-portid"));
1651708Sstevel 		if (mid == NULL) {
1661708Sstevel 			mid = (int *)get_prop_val(find_prop(cpu, "portid"));
1671708Sstevel 		}
1681708Sstevel 
1691708Sstevel 		freq = (get_cpu_freq(cpu) + 500000) / 1000000;
1701708Sstevel 		ecache_size = get_ecache_size(cpu);
1711708Sstevel 		impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
1721708Sstevel 		mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
1731708Sstevel 
1741708Sstevel 		/* Do not display a failed CPU node */
1751708Sstevel 		if ((freq != 0) && (node_failed(cpu) == 0)) {
1761708Sstevel 			/* Board number */
1771708Sstevel 			display_boardnum(board->board_num);
1781708Sstevel 
1791708Sstevel 			/* CPU MID */
1801708Sstevel 			log_printf(" %2d  ", *mid, 0);
1811708Sstevel 
1821708Sstevel 			/* Module number */
1831708Sstevel 			display_mid(*mid);
1841708Sstevel 
1851708Sstevel 			/* Running frequency */
186*5889Szk194757 			log_printf(" %3u   ", freq, 0);
1871708Sstevel 
1881708Sstevel 			/* Ecache size */
1891708Sstevel 			if (ecache_size == 0)
1901708Sstevel 				log_printf(" %3s    ", "N/A", 0);
1911708Sstevel 			else
1921708Sstevel 				log_printf(" %4.1f   ",
193*5889Szk194757 				    (float)ecache_size / (float)(1<<20),
194*5889Szk194757 				    0);
1951708Sstevel 
1961708Sstevel 			/* Implementation */
1971708Sstevel 			if (impl == NULL) {
1981708Sstevel 				log_printf("%6s  ", "N/A", 0);
1991708Sstevel 			} else {
2001708Sstevel 				switch (*impl) {
2011708Sstevel 				case SPITFIRE_IMPL:
2021708Sstevel 					log_printf("%-6s  ", "US-I", 0);
2031708Sstevel 					break;
2041708Sstevel 				case BLACKBIRD_IMPL:
2051708Sstevel 					log_printf("%-6s  ", "US-II", 0);
2061708Sstevel 					break;
2071708Sstevel 				case CHEETAH_IMPL:
2081708Sstevel 					log_printf("%-6s  ", "US-III", 0);
2091708Sstevel 					break;
2101708Sstevel 				case CHEETAH_PLUS_IMPL:
2111708Sstevel 					log_printf("%-7s  ", "US-III+", 0);
2121708Sstevel 					break;
2131708Sstevel 				case JAGUAR_IMPL:
2141708Sstevel 					log_printf("%-6s  ", "US-IV", 0);
2151708Sstevel 					break;
2161708Sstevel 				default:
2171708Sstevel 					log_printf("%-6x  ", *impl, 0);
2181708Sstevel 					break;
2191708Sstevel 				}
2201708Sstevel 			}
2211708Sstevel 
2221708Sstevel 			/* CPU Mask */
2231708Sstevel 			if (mask == NULL) {
2241708Sstevel 				log_printf(" %3s", "N/A", 0);
2251708Sstevel 			} else {
2261708Sstevel 				if ((impl) && IS_CHEETAH(*impl))
2271708Sstevel 					decoded_mask =
228*5889Szk194757 					    REMAP_CHEETAH_MASK(*mask);
2291708Sstevel 				else
2301708Sstevel 					decoded_mask = *mask;
2311708Sstevel 
2321708Sstevel 				log_printf(" %d.%d", (decoded_mask >> 4) & 0xf,
233*5889Szk194757 				    decoded_mask & 0xf, 0);
2341708Sstevel 			}
2351708Sstevel 
2361708Sstevel 			log_printf("\n", 0);
2371708Sstevel 		}
2381708Sstevel 	}
2391708Sstevel }
2401708Sstevel 
2411708Sstevel void
display_mid(int mid)2421708Sstevel display_mid(int mid)
2431708Sstevel {
2441708Sstevel 	log_printf("  %2d     ", mid, 0);
2451708Sstevel }
246