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