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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "mdescplugin.h"
31 /* These 3 variable are defined and set in mdescplugin.c */
32 extern picl_nodehdl_t root_node
;
34 extern mde_cookie_t rootnode
;
37 set_prop_info(ptree_propinfo_t
*propinfo
, int size
, char *name
, int type
)
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
));
50 prop_exists(picl_nodehdl_t node
, char *name
)
55 status
= ptree_get_prop_by_name(node
, name
, &proph
);
56 if (status
== PICL_SUCCESS
)
63 add_md_prop(picl_nodehdl_t node
, int size
, char *name
, void* value
, int type
)
65 ptree_propinfo_t propinfo
;
68 if (!prop_exists(node
, name
)) {
69 set_prop_info(&propinfo
, size
, name
, type
);
71 (void) ptree_create_and_add_prop(node
, &propinfo
,
76 add_tlb_props(picl_nodehdl_t node
, mde_cookie_t
*tlblistp
, int ntlbs
)
82 char property
[MAXSTRLEN
];
83 char tlb_str
[MAXSTRLEN
];
84 int type_size
, str_size
, total_size
, type_flag
;
86 for (i
= 0; i
< ntlbs
; i
++) {
87 if (md_get_prop_data(mdp
, tlblistp
[i
], "type", &type
,
92 total_size
= type_flag
= 0;
94 while (total_size
< type_size
) {
95 str_size
= strlen((char *)type
+ total_size
) + 1;
96 (void) strncpy(str
, (char *)type
+ total_size
,
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
;
107 (void) snprintf(tlb_str
, sizeof (tlb_str
),
111 (void) snprintf(tlb_str
, sizeof (tlb_str
),
115 (void) snprintf(tlb_str
, sizeof (tlb_str
),
116 "Not a known cache type");
119 if (!(md_get_prop_val(mdp
, tlblistp
[i
], "entries",
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
);
130 add_cache_props(picl_nodehdl_t node
, mde_cookie_t
*cachelistp
, int ncaches
)
136 char property
[MAXSTRLEN
];
137 char cache_str
[MAXSTRLEN
];
138 int type_size
, str_size
, total_size
, type_flag
;
140 for (i
= 0; i
< ncaches
; i
++) {
141 if (md_get_prop_data(mdp
, cachelistp
[i
], "type", &type
,
146 if (md_get_prop_val(mdp
, cachelistp
[i
], "level", &int_value
)) {
150 total_size
= type_flag
= 0;
152 while (total_size
< type_size
) {
153 str_size
= strlen((char *)type
+ total_size
) + 1;
154 (void) strncpy(str
, (char *)type
+ total_size
,
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
;
165 (void) snprintf(cache_str
, sizeof (cache_str
),
166 "l%d-icache", (int)int_value
);
169 (void) snprintf(cache_str
, sizeof (cache_str
),
170 "l%d-dcache", (int)int_value
);
173 (void) snprintf(cache_str
, sizeof (cache_str
),
174 "l%d-cache", (int)int_value
);
177 (void) snprintf(cache_str
, sizeof (cache_str
),
178 "Not a known cache type");
181 if (!(md_get_prop_val(mdp
, cachelistp
[i
], "associativity",
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
);
189 if (!(md_get_prop_val(mdp
, cachelistp
[i
], "size",
191 (void) snprintf(property
, sizeof (property
), "%s-size",
193 add_md_prop(node
, sizeof (int_value
), property
,
194 &int_value
, PICL_PTYPE_INT
);
197 if (!(md_get_prop_val(mdp
, cachelistp
[i
], "line-size",
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
);
208 add_clock_frequency(picl_nodehdl_t pnode
, mde_cookie_t mnode
)
210 uint64_t uint64_value
;
211 uint32_t uint32_value
;
213 if (md_get_prop_val(mdp
, mnode
, "clock-frequency",
217 uint32_value
= (uint32_t)(uint64_value
& UINT32_MAX
);
218 add_md_prop(pnode
, sizeof (uint32_value
), "clock-frequency",
219 &uint32_value
, PICL_PTYPE_UNSIGNED_INT
);
223 * Return the number of strings in the buffer
226 get_string_count(char *strdat
, int length
)
233 for (lastnull
= &strdat
[length
- 1], nullptr = strchr(strdat
, '\0');
234 nullptr != lastnull
; nullptr = strchr(nullptr + 1, '\0'))
241 add_compatible(picl_nodehdl_t pnode
, mde_cookie_t mnode
)
246 void add_string_list_prop(picl_nodehdl_t
, char *, char *,
249 if (prop_exists(pnode
, "compatible"))
251 if (md_get_prop_data(mdp
, mnode
, "compatible", (uint8_t **)&compat
,
255 if (compat
[0] == '\0' || compat
[len
- 1] != '\0')
257 count
= get_string_count(compat
, len
);
259 add_md_prop(pnode
, len
, "compatible", compat
,
260 PICL_PTYPE_CHARSTRING
);
263 (void) add_string_list_prop(pnode
, "compatible", compat
, count
);
267 add_device_type(picl_nodehdl_t pnode
)
269 char *device_type
= "cpu";
271 add_md_prop(pnode
, strlen(device_type
) + 1, "device_type", device_type
,
272 PICL_PTYPE_CHARSTRING
);
276 add_cpu_prop(picl_nodehdl_t node
, void *args
)
278 mde_cookie_t
*cpulistp
;
279 mde_cookie_t
*cachelistp
;
280 mde_cookie_t
*tlblistp
;
282 int ncpus
, ncaches
, ntlbs
;
284 int reg_prop
[SUN4V_CPU_REGSIZE
], cpuid
;
285 uint64_t int64_value
;
288 status
= ptree_get_propval_by_name(node
, OBP_REG
, reg_prop
,
290 if (status
!= PICL_SUCCESS
) {
291 return (PICL_WALK_TERMINATE
);
294 cpuid
= CFGHDL_TO_CPUID(reg_prop
[0]);
297 * Allocate space for our searches.
300 num_nodes
= md_node_count(mdp
);
302 cpulistp
= (mde_cookie_t
*) alloca(sizeof (mde_cookie_t
) *num_nodes
);
303 if (cpulistp
== NULL
) {
304 return (PICL_WALK_TERMINATE
);
307 cachelistp
= (mde_cookie_t
*) alloca(sizeof (mde_cookie_t
) *num_nodes
);
308 if (cachelistp
== NULL
) {
309 return (PICL_WALK_TERMINATE
);
312 tlblistp
= (mde_cookie_t
*) alloca(sizeof (mde_cookie_t
) *num_nodes
);
313 if (tlblistp
== NULL
) {
314 return (PICL_WALK_TERMINATE
);
318 * Starting at the root node, scan the "fwd" dag for
319 * all the cpus in this description.
322 ncpus
= md_scan_dag(mdp
, rootnode
, md_find_name(mdp
, "cpu"),
323 md_find_name(mdp
, "fwd"), cpulistp
);
326 return (PICL_WALK_TERMINATE
);
330 * Create PD cpus with a few select properties
333 for (x
= 0; x
< ncpus
; x
++) {
334 if (md_get_prop_val(mdp
, cpulistp
[x
], "id", &int64_value
)) {
338 if (int64_value
!= cpuid
)
341 int_value
= (int)(int64_value
& INT32_MAX
);
343 add_md_prop(node
, sizeof (int_value
), OBP_PROP_CPUID
,
344 &int_value
, PICL_PTYPE_INT
);
346 add_md_prop(node
, sizeof (int_value
), OBP_PROP_PORTID
,
347 &int_value
, PICL_PTYPE_INT
);
349 add_clock_frequency(node
, cpulistp
[x
]);
351 add_compatible(node
, cpulistp
[x
]);
353 add_device_type(node
);
355 /* get caches for CPU */
356 ncaches
= md_scan_dag(mdp
, cpulistp
[x
],
357 md_find_name(mdp
, "cache"),
358 md_find_name(mdp
, "fwd"),
361 add_cache_props(node
, cachelistp
, ncaches
);
363 /* get tlbs for CPU */
364 ntlbs
= md_scan_dag(mdp
, cpulistp
[x
],
365 md_find_name(mdp
, "tlb"),
366 md_find_name(mdp
, "fwd"),
369 add_tlb_props(node
, tlblistp
, ntlbs
);
372 return (PICL_WALK_CONTINUE
);