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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include "mdescplugin.h" 29 #include <limits.h> 30 31 /* These 3 variable are defined and set in mdescplugin.c */ 32 extern picl_nodehdl_t root_node; 33 extern md_t *mdp; 34 extern mde_cookie_t rootnode; 35 36 void 37 set_prop_info(ptree_propinfo_t *propinfo, int size, char *name, int type) 38 { 39 propinfo->version = PICLD_PLUGIN_VERSION_1; 40 propinfo->read = NULL; 41 propinfo->write = NULL; 42 propinfo->piclinfo.type = type; 43 propinfo->piclinfo.accessmode = PICL_READ; 44 propinfo->piclinfo.size = size; 45 (void) strncpy(propinfo->piclinfo.name, name, 46 sizeof (propinfo->piclinfo.name)); 47 } 48 49 static boolean_t 50 prop_exists(picl_nodehdl_t node, char *name) 51 { 52 int status; 53 picl_prophdl_t proph; 54 55 status = ptree_get_prop_by_name(node, name, &proph); 56 if (status == PICL_SUCCESS) 57 return (B_TRUE); 58 else 59 return (B_FALSE); 60 } 61 62 static void 63 add_md_prop(picl_nodehdl_t node, int size, char *name, void* value, int type) 64 { 65 ptree_propinfo_t propinfo; 66 picl_prophdl_t proph; 67 68 if (!prop_exists(node, name)) { 69 set_prop_info(&propinfo, size, name, type); 70 71 (void) ptree_create_and_add_prop(node, &propinfo, 72 value, &proph); 73 } 74 } 75 static void 76 add_tlb_props(picl_nodehdl_t node, mde_cookie_t *tlblistp, int ntlbs) 77 { 78 int i; 79 uint64_t int_value; 80 uint8_t *type; 81 char str[MAXSTRLEN]; 82 char property[MAXSTRLEN]; 83 char tlb_str[MAXSTRLEN]; 84 int type_size, str_size, total_size, type_flag; 85 86 for (i = 0; i < ntlbs; i++) { 87 if (md_get_prop_data(mdp, tlblistp[i], "type", &type, 88 &type_size)) { 89 return; 90 } 91 92 total_size = type_flag = 0; 93 94 while (total_size < type_size) { 95 str_size = strlen((char *)type + total_size) + 1; 96 (void) strncpy(str, (char *)type + total_size, 97 sizeof (str)); 98 if (strncmp(str, "instn", sizeof (str)) == 0) 99 type_flag |= ICACHE_FLAG; 100 if (strncmp(str, "data", sizeof (str)) == 0) 101 type_flag |= DCACHE_FLAG; 102 total_size += str_size; 103 } 104 105 switch (type_flag) { 106 case 1: 107 (void) snprintf(tlb_str, sizeof (tlb_str), 108 "itlb"); 109 break; 110 case 2: 111 (void) snprintf(tlb_str, sizeof (tlb_str), 112 "dtlb"); 113 break; 114 default: 115 (void) snprintf(tlb_str, sizeof (tlb_str), 116 "Not a known cache type"); 117 } 118 119 if (!(md_get_prop_val(mdp, tlblistp[i], "entries", 120 &int_value))) { 121 (void) snprintf(property, sizeof (property), 122 "%s-entries", tlb_str); 123 add_md_prop(node, sizeof (int_value), property, 124 &int_value, PICL_PTYPE_INT); 125 } 126 } 127 } 128 129 static void 130 add_cache_props(picl_nodehdl_t node, mde_cookie_t *cachelistp, int ncaches) 131 { 132 int i; 133 uint64_t int_value; 134 uint8_t *type; 135 char str[MAXSTRLEN]; 136 char property[MAXSTRLEN]; 137 char cache_str[MAXSTRLEN]; 138 int type_size, str_size, total_size, type_flag; 139 140 for (i = 0; i < ncaches; i++) { 141 if (md_get_prop_data(mdp, cachelistp[i], "type", &type, 142 &type_size)) { 143 return; 144 } 145 146 if (md_get_prop_val(mdp, cachelistp[i], "level", &int_value)) { 147 return; 148 } 149 150 total_size = type_flag = 0; 151 152 while (total_size < type_size) { 153 str_size = strlen((char *)type + total_size) + 1; 154 (void) strncpy(str, (char *)type + total_size, 155 sizeof (str)); 156 if (strncmp(str, "instn", sizeof (str)) == 0) 157 type_flag |= ICACHE_FLAG; 158 if (strncmp(str, "data", sizeof (str)) == 0) 159 type_flag |= DCACHE_FLAG; 160 total_size += str_size; 161 } 162 163 switch (type_flag) { 164 case 1: 165 (void) snprintf(cache_str, sizeof (cache_str), 166 "l%d-icache", (int)int_value); 167 break; 168 case 2: 169 (void) snprintf(cache_str, sizeof (cache_str), 170 "l%d-dcache", (int)int_value); 171 break; 172 case 3: 173 (void) snprintf(cache_str, sizeof (cache_str), 174 "l%d-cache", (int)int_value); 175 break; 176 default: 177 (void) snprintf(cache_str, sizeof (cache_str), 178 "Not a known cache type"); 179 } 180 181 if (!(md_get_prop_val(mdp, cachelistp[i], "associativity", 182 &int_value))) { 183 (void) snprintf(property, sizeof (property), 184 "%s-associativity", cache_str); 185 add_md_prop(node, sizeof (int_value), property, 186 &int_value, PICL_PTYPE_INT); 187 } 188 189 if (!(md_get_prop_val(mdp, cachelistp[i], "size", 190 &int_value))) { 191 (void) snprintf(property, sizeof (property), "%s-size", 192 cache_str); 193 add_md_prop(node, sizeof (int_value), property, 194 &int_value, PICL_PTYPE_INT); 195 } 196 197 if (!(md_get_prop_val(mdp, cachelistp[i], "line-size", 198 &int_value))) { 199 (void) snprintf(property, sizeof (property), 200 "%s-line-size", cache_str); 201 add_md_prop(node, sizeof (int_value), property, 202 &int_value, PICL_PTYPE_INT); 203 } 204 } 205 } 206 207 int 208 add_cpu_prop(picl_nodehdl_t node, void *args) 209 { 210 mde_cookie_t *cpulistp; 211 mde_cookie_t *cachelistp; 212 mde_cookie_t *tlblistp; 213 int x, num_nodes; 214 int ncpus, ncaches, ntlbs; 215 int status; 216 int reg_prop[SUN4V_CPU_REGSIZE], cpuid; 217 uint64_t int64_value; 218 int int_value; 219 220 status = ptree_get_propval_by_name(node, OBP_REG, reg_prop, 221 sizeof (reg_prop)); 222 if (status != PICL_SUCCESS) { 223 return (PICL_WALK_TERMINATE); 224 } 225 226 cpuid = CFGHDL_TO_CPUID(reg_prop[0]); 227 228 /* 229 * Allocate space for our searches. 230 */ 231 232 num_nodes = md_node_count(mdp); 233 234 cpulistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); 235 if (cpulistp == NULL) { 236 return (PICL_WALK_TERMINATE); 237 } 238 239 cachelistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); 240 if (cachelistp == NULL) { 241 return (PICL_WALK_TERMINATE); 242 } 243 244 tlblistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); 245 if (tlblistp == NULL) { 246 return (PICL_WALK_TERMINATE); 247 } 248 249 /* 250 * Starting at the root node, scan the "fwd" dag for 251 * all the cpus in this description. 252 */ 253 254 ncpus = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"), 255 md_find_name(mdp, "fwd"), cpulistp); 256 257 if (ncpus < 0) { 258 return (PICL_WALK_TERMINATE); 259 } 260 261 /* 262 * Create PD cpus with a few select properties 263 */ 264 265 for (x = 0; x < ncpus; x++) { 266 if (md_get_prop_val(mdp, cpulistp[x], "id", &int64_value)) { 267 continue; 268 } 269 270 if (int64_value != cpuid) 271 continue; 272 273 int_value = (int)(int64_value & INT32_MAX); 274 275 add_md_prop(node, sizeof (int_value), OBP_PROP_CPUID, 276 &int_value, PICL_PTYPE_INT); 277 278 add_md_prop(node, sizeof (int_value), OBP_PROP_PORTID, 279 &int_value, PICL_PTYPE_INT); 280 281 /* get caches for CPU */ 282 ncaches = md_scan_dag(mdp, cpulistp[x], 283 md_find_name(mdp, "cache"), 284 md_find_name(mdp, "fwd"), 285 cachelistp); 286 287 add_cache_props(node, cachelistp, ncaches); 288 289 /* get tlbs for CPU */ 290 ntlbs = md_scan_dag(mdp, cpulistp[x], 291 md_find_name(mdp, "tlb"), 292 md_find_name(mdp, "fwd"), 293 tlblistp); 294 295 add_tlb_props(node, tlblistp, ntlbs); 296 } 297 298 return (PICL_WALK_CONTINUE); 299 } 300