xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4v/mdesc/cpu_prop_update.c (revision 99dda20867d903eec23291ba1ecb18a82d70096b)
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