10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51991Sheppo * Common Development and Distribution License (the "License").
61991Sheppo * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*6902Smb158278 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include "mdescplugin.h"
295028Sfw157321 #include <limits.h>
300Sstevel@tonic-gate
310Sstevel@tonic-gate /* These 3 variable are defined and set in mdescplugin.c */
320Sstevel@tonic-gate extern picl_nodehdl_t root_node;
330Sstevel@tonic-gate extern md_t *mdp;
340Sstevel@tonic-gate extern mde_cookie_t rootnode;
350Sstevel@tonic-gate
360Sstevel@tonic-gate void
set_prop_info(ptree_propinfo_t * propinfo,int size,char * name,int type)370Sstevel@tonic-gate set_prop_info(ptree_propinfo_t *propinfo, int size, char *name, int type)
380Sstevel@tonic-gate {
390Sstevel@tonic-gate propinfo->version = PICLD_PLUGIN_VERSION_1;
400Sstevel@tonic-gate propinfo->read = NULL;
410Sstevel@tonic-gate propinfo->write = NULL;
420Sstevel@tonic-gate propinfo->piclinfo.type = type;
430Sstevel@tonic-gate propinfo->piclinfo.accessmode = PICL_READ;
440Sstevel@tonic-gate propinfo->piclinfo.size = size;
450Sstevel@tonic-gate (void) strncpy(propinfo->piclinfo.name, name,
460Sstevel@tonic-gate sizeof (propinfo->piclinfo.name));
470Sstevel@tonic-gate }
480Sstevel@tonic-gate
490Sstevel@tonic-gate static boolean_t
prop_exists(picl_nodehdl_t node,char * name)500Sstevel@tonic-gate prop_exists(picl_nodehdl_t node, char *name)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate int status;
530Sstevel@tonic-gate picl_prophdl_t proph;
540Sstevel@tonic-gate
550Sstevel@tonic-gate status = ptree_get_prop_by_name(node, name, &proph);
560Sstevel@tonic-gate if (status == PICL_SUCCESS)
570Sstevel@tonic-gate return (B_TRUE);
580Sstevel@tonic-gate else
590Sstevel@tonic-gate return (B_FALSE);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate static void
add_md_prop(picl_nodehdl_t node,int size,char * name,void * value,int type)630Sstevel@tonic-gate add_md_prop(picl_nodehdl_t node, int size, char *name, void* value, int type)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate ptree_propinfo_t propinfo;
660Sstevel@tonic-gate picl_prophdl_t proph;
670Sstevel@tonic-gate
680Sstevel@tonic-gate if (!prop_exists(node, name)) {
690Sstevel@tonic-gate set_prop_info(&propinfo, size, name, type);
700Sstevel@tonic-gate
710Sstevel@tonic-gate (void) ptree_create_and_add_prop(node, &propinfo,
720Sstevel@tonic-gate value, &proph);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate }
750Sstevel@tonic-gate static void
add_tlb_props(picl_nodehdl_t node,mde_cookie_t * tlblistp,int ntlbs)760Sstevel@tonic-gate add_tlb_props(picl_nodehdl_t node, mde_cookie_t *tlblistp, int ntlbs)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate int i;
790Sstevel@tonic-gate uint64_t int_value;
800Sstevel@tonic-gate uint8_t *type;
810Sstevel@tonic-gate char str[MAXSTRLEN];
820Sstevel@tonic-gate char property[MAXSTRLEN];
830Sstevel@tonic-gate char tlb_str[MAXSTRLEN];
840Sstevel@tonic-gate int type_size, str_size, total_size, type_flag;
850Sstevel@tonic-gate
860Sstevel@tonic-gate for (i = 0; i < ntlbs; i++) {
870Sstevel@tonic-gate if (md_get_prop_data(mdp, tlblistp[i], "type", &type,
885028Sfw157321 &type_size)) {
890Sstevel@tonic-gate return;
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate total_size = type_flag = 0;
930Sstevel@tonic-gate
940Sstevel@tonic-gate while (total_size < type_size) {
950Sstevel@tonic-gate str_size = strlen((char *)type + total_size) + 1;
960Sstevel@tonic-gate (void) strncpy(str, (char *)type + total_size,
970Sstevel@tonic-gate sizeof (str));
980Sstevel@tonic-gate if (strncmp(str, "instn", sizeof (str)) == 0)
990Sstevel@tonic-gate type_flag |= ICACHE_FLAG;
1000Sstevel@tonic-gate if (strncmp(str, "data", sizeof (str)) == 0)
1010Sstevel@tonic-gate type_flag |= DCACHE_FLAG;
1020Sstevel@tonic-gate total_size += str_size;
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate switch (type_flag) {
1060Sstevel@tonic-gate case 1:
1070Sstevel@tonic-gate (void) snprintf(tlb_str, sizeof (tlb_str),
1080Sstevel@tonic-gate "itlb");
1090Sstevel@tonic-gate break;
1100Sstevel@tonic-gate case 2:
1110Sstevel@tonic-gate (void) snprintf(tlb_str, sizeof (tlb_str),
1120Sstevel@tonic-gate "dtlb");
1130Sstevel@tonic-gate break;
1140Sstevel@tonic-gate default:
1150Sstevel@tonic-gate (void) snprintf(tlb_str, sizeof (tlb_str),
1160Sstevel@tonic-gate "Not a known cache type");
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate if (!(md_get_prop_val(mdp, tlblistp[i], "entries",
1205028Sfw157321 &int_value))) {
1210Sstevel@tonic-gate (void) snprintf(property, sizeof (property),
1220Sstevel@tonic-gate "%s-entries", tlb_str);
1230Sstevel@tonic-gate add_md_prop(node, sizeof (int_value), property,
1240Sstevel@tonic-gate &int_value, PICL_PTYPE_INT);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate static void
add_cache_props(picl_nodehdl_t node,mde_cookie_t * cachelistp,int ncaches)1300Sstevel@tonic-gate add_cache_props(picl_nodehdl_t node, mde_cookie_t *cachelistp, int ncaches)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate int i;
1330Sstevel@tonic-gate uint64_t int_value;
1340Sstevel@tonic-gate uint8_t *type;
1350Sstevel@tonic-gate char str[MAXSTRLEN];
1360Sstevel@tonic-gate char property[MAXSTRLEN];
1370Sstevel@tonic-gate char cache_str[MAXSTRLEN];
1380Sstevel@tonic-gate int type_size, str_size, total_size, type_flag;
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate for (i = 0; i < ncaches; i++) {
1410Sstevel@tonic-gate if (md_get_prop_data(mdp, cachelistp[i], "type", &type,
1425028Sfw157321 &type_size)) {
1430Sstevel@tonic-gate return;
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate if (md_get_prop_val(mdp, cachelistp[i], "level", &int_value)) {
1470Sstevel@tonic-gate return;
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate total_size = type_flag = 0;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate while (total_size < type_size) {
1530Sstevel@tonic-gate str_size = strlen((char *)type + total_size) + 1;
1540Sstevel@tonic-gate (void) strncpy(str, (char *)type + total_size,
1550Sstevel@tonic-gate sizeof (str));
1560Sstevel@tonic-gate if (strncmp(str, "instn", sizeof (str)) == 0)
1570Sstevel@tonic-gate type_flag |= ICACHE_FLAG;
1580Sstevel@tonic-gate if (strncmp(str, "data", sizeof (str)) == 0)
1590Sstevel@tonic-gate type_flag |= DCACHE_FLAG;
1600Sstevel@tonic-gate total_size += str_size;
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate switch (type_flag) {
1640Sstevel@tonic-gate case 1:
1650Sstevel@tonic-gate (void) snprintf(cache_str, sizeof (cache_str),
1660Sstevel@tonic-gate "l%d-icache", (int)int_value);
1670Sstevel@tonic-gate break;
1680Sstevel@tonic-gate case 2:
1690Sstevel@tonic-gate (void) snprintf(cache_str, sizeof (cache_str),
1700Sstevel@tonic-gate "l%d-dcache", (int)int_value);
1710Sstevel@tonic-gate break;
1720Sstevel@tonic-gate case 3:
1730Sstevel@tonic-gate (void) snprintf(cache_str, sizeof (cache_str),
1740Sstevel@tonic-gate "l%d-cache", (int)int_value);
1750Sstevel@tonic-gate break;
1760Sstevel@tonic-gate default:
1770Sstevel@tonic-gate (void) snprintf(cache_str, sizeof (cache_str),
1780Sstevel@tonic-gate "Not a known cache type");
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate if (!(md_get_prop_val(mdp, cachelistp[i], "associativity",
1825028Sfw157321 &int_value))) {
1830Sstevel@tonic-gate (void) snprintf(property, sizeof (property),
1840Sstevel@tonic-gate "%s-associativity", cache_str);
1850Sstevel@tonic-gate add_md_prop(node, sizeof (int_value), property,
1860Sstevel@tonic-gate &int_value, PICL_PTYPE_INT);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate if (!(md_get_prop_val(mdp, cachelistp[i], "size",
1905028Sfw157321 &int_value))) {
1910Sstevel@tonic-gate (void) snprintf(property, sizeof (property), "%s-size",
1920Sstevel@tonic-gate cache_str);
1930Sstevel@tonic-gate add_md_prop(node, sizeof (int_value), property,
1940Sstevel@tonic-gate &int_value, PICL_PTYPE_INT);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate if (!(md_get_prop_val(mdp, cachelistp[i], "line-size",
1985028Sfw157321 &int_value))) {
1990Sstevel@tonic-gate (void) snprintf(property, sizeof (property),
2000Sstevel@tonic-gate "%s-line-size", cache_str);
2010Sstevel@tonic-gate add_md_prop(node, sizeof (int_value), property,
2020Sstevel@tonic-gate &int_value, PICL_PTYPE_INT);
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate
207*6902Smb158278 static void
add_clock_frequency(picl_nodehdl_t pnode,mde_cookie_t mnode)208*6902Smb158278 add_clock_frequency(picl_nodehdl_t pnode, mde_cookie_t mnode)
209*6902Smb158278 {
210*6902Smb158278 uint64_t uint64_value;
211*6902Smb158278 uint32_t uint32_value;
212*6902Smb158278
213*6902Smb158278 if (md_get_prop_val(mdp, mnode, "clock-frequency",
214*6902Smb158278 &uint64_value)) {
215*6902Smb158278 return;
216*6902Smb158278 }
217*6902Smb158278 uint32_value = (uint32_t)(uint64_value & UINT32_MAX);
218*6902Smb158278 add_md_prop(pnode, sizeof (uint32_value), "clock-frequency",
219*6902Smb158278 &uint32_value, PICL_PTYPE_UNSIGNED_INT);
220*6902Smb158278 }
221*6902Smb158278
222*6902Smb158278 /*
223*6902Smb158278 * Return the number of strings in the buffer
224*6902Smb158278 */
225*6902Smb158278 static int
get_string_count(char * strdat,int length)226*6902Smb158278 get_string_count(char *strdat, int length)
227*6902Smb158278 {
228*6902Smb158278 int count;
229*6902Smb158278 char *lastnull;
230*6902Smb158278 char *nullptr;
231*6902Smb158278
232*6902Smb158278 count = 1;
233*6902Smb158278 for (lastnull = &strdat[length - 1], nullptr = strchr(strdat, '\0');
234*6902Smb158278 nullptr != lastnull; nullptr = strchr(nullptr + 1, '\0'))
235*6902Smb158278 count++;
236*6902Smb158278
237*6902Smb158278 return (count);
238*6902Smb158278 }
239*6902Smb158278
240*6902Smb158278 static void
add_compatible(picl_nodehdl_t pnode,mde_cookie_t mnode)241*6902Smb158278 add_compatible(picl_nodehdl_t pnode, mde_cookie_t mnode)
242*6902Smb158278 {
243*6902Smb158278 char *compat;
244*6902Smb158278 int len;
245*6902Smb158278 int count;
246*6902Smb158278 void add_string_list_prop(picl_nodehdl_t, char *, char *,
247*6902Smb158278 unsigned int);
248*6902Smb158278
249*6902Smb158278 if (prop_exists(pnode, "compatible"))
250*6902Smb158278 return;
251*6902Smb158278 if (md_get_prop_data(mdp, mnode, "compatible", (uint8_t **)&compat,
252*6902Smb158278 &len)) {
253*6902Smb158278 return;
254*6902Smb158278 }
255*6902Smb158278 if (compat[0] == '\0' || compat[len - 1] != '\0')
256*6902Smb158278 return;
257*6902Smb158278 count = get_string_count(compat, len);
258*6902Smb158278 if (count == 1) {
259*6902Smb158278 add_md_prop(pnode, len, "compatible", compat,
260*6902Smb158278 PICL_PTYPE_CHARSTRING);
261*6902Smb158278 return;
262*6902Smb158278 }
263*6902Smb158278 (void) add_string_list_prop(pnode, "compatible", compat, count);
264*6902Smb158278 }
265*6902Smb158278
266*6902Smb158278 static void
add_device_type(picl_nodehdl_t pnode)267*6902Smb158278 add_device_type(picl_nodehdl_t pnode)
268*6902Smb158278 {
269*6902Smb158278 char *device_type = "cpu";
270*6902Smb158278
271*6902Smb158278 add_md_prop(pnode, strlen(device_type) + 1, "device_type", device_type,
272*6902Smb158278 PICL_PTYPE_CHARSTRING);
273*6902Smb158278 }
274*6902Smb158278
2750Sstevel@tonic-gate int
add_cpu_prop(picl_nodehdl_t node,void * args)2760Sstevel@tonic-gate add_cpu_prop(picl_nodehdl_t node, void *args)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate mde_cookie_t *cpulistp;
2790Sstevel@tonic-gate mde_cookie_t *cachelistp;
2800Sstevel@tonic-gate mde_cookie_t *tlblistp;
2810Sstevel@tonic-gate int x, num_nodes;
2820Sstevel@tonic-gate int ncpus, ncaches, ntlbs;
2830Sstevel@tonic-gate int status;
2841991Sheppo int reg_prop[SUN4V_CPU_REGSIZE], cpuid;
2855028Sfw157321 uint64_t int64_value;
2865028Sfw157321 int int_value;
2870Sstevel@tonic-gate
2881991Sheppo status = ptree_get_propval_by_name(node, OBP_REG, reg_prop,
2890Sstevel@tonic-gate sizeof (reg_prop));
2900Sstevel@tonic-gate if (status != PICL_SUCCESS) {
2910Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2941991Sheppo cpuid = CFGHDL_TO_CPUID(reg_prop[0]);
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate * Allocate space for our searches.
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate num_nodes = md_node_count(mdp);
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate cpulistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
3030Sstevel@tonic-gate if (cpulistp == NULL) {
3040Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate cachelistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
3080Sstevel@tonic-gate if (cachelistp == NULL) {
3090Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate tlblistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes);
3130Sstevel@tonic-gate if (tlblistp == NULL) {
3140Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*
3180Sstevel@tonic-gate * Starting at the root node, scan the "fwd" dag for
3190Sstevel@tonic-gate * all the cpus in this description.
3200Sstevel@tonic-gate */
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate ncpus = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"),
3230Sstevel@tonic-gate md_find_name(mdp, "fwd"), cpulistp);
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate if (ncpus < 0) {
3260Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /*
3300Sstevel@tonic-gate * Create PD cpus with a few select properties
3310Sstevel@tonic-gate */
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate for (x = 0; x < ncpus; x++) {
3345028Sfw157321 if (md_get_prop_val(mdp, cpulistp[x], "id", &int64_value)) {
3350Sstevel@tonic-gate continue;
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3385028Sfw157321 if (int64_value != cpuid)
3390Sstevel@tonic-gate continue;
3400Sstevel@tonic-gate
3415028Sfw157321 int_value = (int)(int64_value & INT32_MAX);
3420Sstevel@tonic-gate
3435028Sfw157321 add_md_prop(node, sizeof (int_value), OBP_PROP_CPUID,
3445028Sfw157321 &int_value, PICL_PTYPE_INT);
3455028Sfw157321
3465028Sfw157321 add_md_prop(node, sizeof (int_value), OBP_PROP_PORTID,
3475028Sfw157321 &int_value, PICL_PTYPE_INT);
3480Sstevel@tonic-gate
349*6902Smb158278 add_clock_frequency(node, cpulistp[x]);
350*6902Smb158278
351*6902Smb158278 add_compatible(node, cpulistp[x]);
352*6902Smb158278
353*6902Smb158278 add_device_type(node);
354*6902Smb158278
3550Sstevel@tonic-gate /* get caches for CPU */
3560Sstevel@tonic-gate ncaches = md_scan_dag(mdp, cpulistp[x],
3570Sstevel@tonic-gate md_find_name(mdp, "cache"),
3580Sstevel@tonic-gate md_find_name(mdp, "fwd"),
3590Sstevel@tonic-gate cachelistp);
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate add_cache_props(node, cachelistp, ncaches);
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate /* get tlbs for CPU */
3640Sstevel@tonic-gate ntlbs = md_scan_dag(mdp, cpulistp[x],
3650Sstevel@tonic-gate md_find_name(mdp, "tlb"),
3660Sstevel@tonic-gate md_find_name(mdp, "fwd"),
3670Sstevel@tonic-gate tlblistp);
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate add_tlb_props(node, tlblistp, ntlbs);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate return (PICL_WALK_CONTINUE);
3730Sstevel@tonic-gate }
374