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