11708Sstevel /* 21708Sstevel * CDDL HEADER START 31708Sstevel * 41708Sstevel * The contents of this file are subject to the terms of the 5*1772Sjl139090 * Common Development and Distribution License (the "License"). 6*1772Sjl139090 * 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*1772Sjl139090 * Copyright 2006 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 */ 61*1772Sjl139090 uint_t 621708Sstevel get_cpu_freq(Prom_node *pnode) 631708Sstevel { 641708Sstevel Prop *prop; 65*1772Sjl139090 uint_t *value; 661708Sstevel 671708Sstevel /* find the property */ 681708Sstevel if ((prop = find_prop(pnode, "clock-frequency")) == NULL) { 691708Sstevel return (0); 701708Sstevel } 711708Sstevel 72*1772Sjl139090 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 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, 911708Sstevel "ecache-size"))) { 921708Sstevel return (*cache_size_p); 931708Sstevel } 941708Sstevel if (cache_size_p = (int *)get_prop_val(find_prop(node, 951708Sstevel "l3-cache-size"))) { 961708Sstevel return (*cache_size_p); 971708Sstevel } 981708Sstevel if (cache_size_p = (int *)get_prop_val(find_prop(node, 991708Sstevel "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 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 " 1281708Sstevel " CPU CPU\n", 0); 1291708Sstevel log_printf("Brd CPU Module MHz MB " 1301708Sstevel "Impl. Mask\n", 0); 1311708Sstevel log_printf("--- --- ------- ----- ------ " 1321708Sstevel "------ ----\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 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")) { 1581708Sstevel int 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 */ 1861708Sstevel log_printf(" %3d ", 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 ", 1931708Sstevel (float)ecache_size / (float)(1<<20), 1941708Sstevel 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 = 2281708Sstevel REMAP_CHEETAH_MASK(*mask); 2291708Sstevel else 2301708Sstevel decoded_mask = *mask; 2311708Sstevel 2321708Sstevel log_printf(" %d.%d", (decoded_mask >> 4) & 0xf, 2331708Sstevel decoded_mask & 0xf, 0); 2341708Sstevel } 2351708Sstevel 2361708Sstevel log_printf("\n", 0); 2371708Sstevel } 2381708Sstevel } 2391708Sstevel } 2401708Sstevel 2411708Sstevel void 2421708Sstevel display_mid(int mid) 2431708Sstevel { 2441708Sstevel log_printf(" %2d ", mid, 0); 2451708Sstevel } 246