Home | History | Annotate | Download | only in common
      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