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