xref: /titanic_51/usr/src/lib/libprtdiag/common/cpu.c (revision e79c98e6c943cb3032f272714ff4ce6137d40394)
103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
525cf1a30Sjl139090  * Common Development and Distribution License (the "License").
625cf1a30Sjl139090  * You may not use this file except in compliance with the License.
703831d35Sstevel  *
803831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel  * See the License for the specific language governing permissions
1103831d35Sstevel  * and limitations under the License.
1203831d35Sstevel  *
1303831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel  *
1903831d35Sstevel  * CDDL HEADER END
2003831d35Sstevel  */
2103831d35Sstevel /*
22*e79c98e6Szk194757  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2303831d35Sstevel  * Use is subject to license terms.
2403831d35Sstevel  */
2503831d35Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
2603831d35Sstevel 
2703831d35Sstevel #include <stdio.h>
2803831d35Sstevel #include <stdlib.h>
2903831d35Sstevel #include <unistd.h>
3003831d35Sstevel #include <ctype.h>
3103831d35Sstevel #include <string.h>
3203831d35Sstevel #include <kvm.h>
3303831d35Sstevel #include <varargs.h>
3403831d35Sstevel #include <errno.h>
3503831d35Sstevel #include <time.h>
3603831d35Sstevel #include <dirent.h>
3703831d35Sstevel #include <fcntl.h>
3803831d35Sstevel #include <sys/param.h>
3903831d35Sstevel #include <sys/stat.h>
4003831d35Sstevel #include <sys/types.h>
4103831d35Sstevel #include <sys/utsname.h>
4203831d35Sstevel #include <sys/openpromio.h>
4303831d35Sstevel #include <sys/spitregs.h>
4403831d35Sstevel #include <sys/cheetahregs.h>
4503831d35Sstevel #include <kstat.h>
4603831d35Sstevel #include <libintl.h>
4703831d35Sstevel #include <syslog.h>
4803831d35Sstevel #include <sys/dkio.h>
4903831d35Sstevel #include "pdevinfo.h"
5003831d35Sstevel #include "display.h"
5103831d35Sstevel #include "pdevinfo_sun4u.h"
5203831d35Sstevel #include "display_sun4u.h"
5303831d35Sstevel #include "libprtdiag.h"
5403831d35Sstevel 
5503831d35Sstevel /*
5603831d35Sstevel  * Return the operating frequency of a processor in Hertz. This function
5703831d35Sstevel  * requires as input a legal prom node pointer. If a NULL
5803831d35Sstevel  * is passed in or the clock-frequency property does not exist, the
5903831d35Sstevel  * function returns 0.
6003831d35Sstevel  */
6125cf1a30Sjl139090 uint_t
6203831d35Sstevel get_cpu_freq(Prom_node *pnode)
6303831d35Sstevel {
6403831d35Sstevel 	Prop *prop;
6525cf1a30Sjl139090 	uint_t *value;
6603831d35Sstevel 
6703831d35Sstevel 	/* find the property */
6803831d35Sstevel 	if ((prop = find_prop(pnode, "clock-frequency")) == NULL) {
6903831d35Sstevel 		return (0);
7003831d35Sstevel 	}
7103831d35Sstevel 
7225cf1a30Sjl139090 	if ((value = (uint_t *)get_prop_val(prop)) == NULL) {
7303831d35Sstevel 		return (0);
7403831d35Sstevel 	}
7503831d35Sstevel 
7603831d35Sstevel 	return (*value);
7703831d35Sstevel }
7803831d35Sstevel 
7903831d35Sstevel /*
8003831d35Sstevel  * returns the size of the given processors external cache in
8103831d35Sstevel  * bytes. If the properties required to determine this are not
8203831d35Sstevel  * present, then the function returns 0.
8303831d35Sstevel  */
8403831d35Sstevel int
8503831d35Sstevel get_ecache_size(Prom_node *node)
8603831d35Sstevel {
8703831d35Sstevel 	int *cache_size_p;	/* pointer to number of cache lines */
8803831d35Sstevel 
8903831d35Sstevel 	/* find the properties */
9003831d35Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
9103831d35Sstevel 	    "ecache-size"))) {
9203831d35Sstevel 		return (*cache_size_p);
9303831d35Sstevel 	}
9403831d35Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
9503831d35Sstevel 	    "l3-cache-size"))) {
9603831d35Sstevel 		return (*cache_size_p);
9703831d35Sstevel 	}
9803831d35Sstevel 	if (cache_size_p = (int *)get_prop_val(find_prop(node,
9903831d35Sstevel 	    "l2-cache-size"))) {
10003831d35Sstevel 		return (*cache_size_p);
10103831d35Sstevel 	}
10203831d35Sstevel 
10303831d35Sstevel 	return (0);
10403831d35Sstevel }
10503831d35Sstevel 
10603831d35Sstevel 
10703831d35Sstevel /*
10803831d35Sstevel  * This routine is the generic link into displaying CPU and memory info.
10903831d35Sstevel  * It displays the table header, then calls the CPU and memory display
11003831d35Sstevel  * routine for all boards.
11103831d35Sstevel  */
11203831d35Sstevel void
11303831d35Sstevel display_cpu_devices(Sys_tree *tree)
11403831d35Sstevel {
11503831d35Sstevel 	Board_node *bnode;
11603831d35Sstevel 
11703831d35Sstevel 	/*
11803831d35Sstevel 	 * Display the table header for CPUs . Then display the CPU
11903831d35Sstevel 	 * frequency, cache size, and processor revision of all cpus.
12003831d35Sstevel 	 */
12103831d35Sstevel 	log_printf("\n", 0);
12203831d35Sstevel 	log_printf("=========================", 0);
12303831d35Sstevel 	log_printf(" CPUs ", 0);
12403831d35Sstevel 	log_printf("=========================", 0);
12503831d35Sstevel 	log_printf("\n", 0);
12603831d35Sstevel 	log_printf("\n", 0);
12703831d35Sstevel 	log_printf("                    Run   Ecache  "
12803831d35Sstevel 	    " CPU    CPU\n", 0);
12903831d35Sstevel 	log_printf("Brd  CPU   Module   MHz     MB    "
13003831d35Sstevel 	    "Impl.   Mask\n", 0);
13103831d35Sstevel 	log_printf("---  ---  -------  -----  ------  "
13203831d35Sstevel 	    "------  ----\n", 0);
13303831d35Sstevel 
13403831d35Sstevel 	/* Now display all of the cpus on each board */
13503831d35Sstevel 	bnode = tree->bd_list;
13603831d35Sstevel 	while (bnode != NULL) {
13703831d35Sstevel 		display_cpus(bnode);
13803831d35Sstevel 	bnode = bnode->next;
13903831d35Sstevel 	}
14003831d35Sstevel 
14103831d35Sstevel 	log_printf("\n", 0);
14203831d35Sstevel }
14303831d35Sstevel 
14403831d35Sstevel /*
14503831d35Sstevel  * Display the CPUs present on this board.
14603831d35Sstevel  */
14703831d35Sstevel void
14803831d35Sstevel display_cpus(Board_node *board)
14903831d35Sstevel {
15003831d35Sstevel 	Prom_node *cpu;
15103831d35Sstevel 
15203831d35Sstevel 	/*
15303831d35Sstevel 	 * display the CPUs' operating frequency, cache size, impl. field
15403831d35Sstevel 	 * and mask revision.
15503831d35Sstevel 	 */
15603831d35Sstevel 	for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
15703831d35Sstevel 	    cpu = dev_next_type(cpu, "cpu")) {
158*e79c98e6Szk194757 		uint_t freq;	 /* CPU clock frequency */
15903831d35Sstevel 		int ecache_size; /* External cache size */
16003831d35Sstevel 		int *mid;
16103831d35Sstevel 		int *impl;
16203831d35Sstevel 		int *mask, decoded_mask;
16303831d35Sstevel 
16403831d35Sstevel 		mid = (int *)get_prop_val(find_prop(cpu, "upa-portid"));
16503831d35Sstevel 		if (mid == NULL) {
16603831d35Sstevel 			mid = (int *)get_prop_val(find_prop(cpu, "portid"));
16703831d35Sstevel 		}
16803831d35Sstevel 
16903831d35Sstevel 		freq = (get_cpu_freq(cpu) + 500000) / 1000000;
17003831d35Sstevel 		ecache_size = get_ecache_size(cpu);
17103831d35Sstevel 		impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
17203831d35Sstevel 		mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
17303831d35Sstevel 
17403831d35Sstevel 		/* Do not display a failed CPU node */
17503831d35Sstevel 		if ((freq != 0) && (node_failed(cpu) == 0)) {
17603831d35Sstevel 			/* Board number */
17703831d35Sstevel 			display_boardnum(board->board_num);
17803831d35Sstevel 
17903831d35Sstevel 			/* CPU MID */
18003831d35Sstevel 			log_printf(" %2d  ", *mid, 0);
18103831d35Sstevel 
18203831d35Sstevel 			/* Module number */
18303831d35Sstevel 			display_mid(*mid);
18403831d35Sstevel 
18503831d35Sstevel 			/* Running frequency */
186*e79c98e6Szk194757 			log_printf(" %3u   ", freq, 0);
18703831d35Sstevel 
18803831d35Sstevel 			/* Ecache size */
18903831d35Sstevel 			if (ecache_size == 0)
19003831d35Sstevel 				log_printf(" %3s    ", "N/A", 0);
19103831d35Sstevel 			else
19203831d35Sstevel 				log_printf(" %4.1f   ",
19303831d35Sstevel 				    (float)ecache_size / (float)(1<<20),
19403831d35Sstevel 				    0);
19503831d35Sstevel 
19603831d35Sstevel 			/* Implementation */
19703831d35Sstevel 			if (impl == NULL) {
19803831d35Sstevel 				log_printf("%6s  ", "N/A", 0);
19903831d35Sstevel 			} else {
20003831d35Sstevel 				switch (*impl) {
20103831d35Sstevel 				case SPITFIRE_IMPL:
20203831d35Sstevel 					log_printf("%-6s  ", "US-I", 0);
20303831d35Sstevel 					break;
20403831d35Sstevel 				case BLACKBIRD_IMPL:
20503831d35Sstevel 					log_printf("%-6s  ", "US-II", 0);
20603831d35Sstevel 					break;
20703831d35Sstevel 				case CHEETAH_IMPL:
20803831d35Sstevel 					log_printf("%-6s  ", "US-III", 0);
20903831d35Sstevel 					break;
21003831d35Sstevel 				case CHEETAH_PLUS_IMPL:
21103831d35Sstevel 					log_printf("%-7s  ", "US-III+", 0);
21203831d35Sstevel 					break;
21303831d35Sstevel 				case JAGUAR_IMPL:
21403831d35Sstevel 					log_printf("%-6s  ", "US-IV", 0);
21503831d35Sstevel 					break;
21603831d35Sstevel 				default:
21703831d35Sstevel 					log_printf("%-6x  ", *impl, 0);
21803831d35Sstevel 					break;
21903831d35Sstevel 				}
22003831d35Sstevel 			}
22103831d35Sstevel 
22203831d35Sstevel 			/* CPU Mask */
22303831d35Sstevel 			if (mask == NULL) {
22403831d35Sstevel 				log_printf(" %3s", "N/A", 0);
22503831d35Sstevel 			} else {
22603831d35Sstevel 				if ((impl) && IS_CHEETAH(*impl))
22703831d35Sstevel 					decoded_mask =
22803831d35Sstevel 					    REMAP_CHEETAH_MASK(*mask);
22903831d35Sstevel 				else
23003831d35Sstevel 					decoded_mask = *mask;
23103831d35Sstevel 
23203831d35Sstevel 				log_printf(" %d.%d", (decoded_mask >> 4) & 0xf,
23303831d35Sstevel 				    decoded_mask & 0xf, 0);
23403831d35Sstevel 			}
23503831d35Sstevel 
23603831d35Sstevel 			log_printf("\n", 0);
23703831d35Sstevel 		}
23803831d35Sstevel 	}
23903831d35Sstevel }
24003831d35Sstevel 
24103831d35Sstevel void
24203831d35Sstevel display_mid(int mid)
24303831d35Sstevel {
24403831d35Sstevel 	log_printf("  %2d     ", mid, 0);
24503831d35Sstevel }
246