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