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