xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/grover/memcfg/piclmemcfg.c (revision 69a119caa6570c7077699161b7c28b6ee9f8b0f4)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This plugin creates memory configuration nodes and properties in the
31  * PICL tree for Grover/Grover+ platform.
32  *
33  * Subtree of memory-controller in the physical aspect.
34  * memory-controller --- memory-module
35  * However, there is no memory controller node on Grover. Thus we need to
36  * create it under platform.
37  *
38  * Subtree of memory in the logical aspect.
39  * memory --- memory-segment
40  * Add property _memory-module_ at memory-segment referring to the
41  * memory-module since memory-segment equals to memory-module on Grover.
42  *
43  * Undo strategy:
44  * Create all nodes and properties, or none if it fails in physical and
45  * logical memory tree respectively. It keeps on creating logical
46  * memory tree although it falis on physical logical tree, but no link to
47  * memory module.
48  *
49  * NOTE:
50  * It depends on PICL devtree plugin.
51  */
52 
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <unistd.h>
56 #include <alloca.h>
57 #include <syslog.h>
58 #include <string.h>
59 #include <libintl.h>
60 #include <picl.h>
61 #include <picltree.h>
62 #include <sys/types.h>
63 #include <sys/obpdefs.h>
64 #include "piclmemcfg.h"
65 #include "memcfg_impl.h"
66 
67 static	void	piclmemcfg_register(void);
68 static	void	piclmemcfg_init(void);
69 static	void	piclmemcfg_fini(void);
70 
71 #pragma	init(piclmemcfg_register)
72 
73 static picld_plugin_reg_t  my_reg_info = {
74 	PICLD_PLUGIN_VERSION_1,
75 	PICLD_PLUGIN_NON_CRITICAL,
76 	"SUNW_piclmemcfg",
77 	piclmemcfg_init,
78 	piclmemcfg_fini
79 };
80 
81 /*
82  * Create logical memory tree
83  * memory --- memory-segment
84  */
85 static int
86 create_logical_tree(picl_nodehdl_t memh, mmodinfo_t *mmodinfo)
87 {
88 	picl_nodehdl_t		msegh;
89 	picl_nodehdl_t		*memsegh;
90 	ptree_propinfo_t	propinfo;
91 	uint32_t		ifactor = INTERLEAVEFACTOR;
92 	int			i;
93 	int			err = PICL_SUCCESS;
94 
95 	if ((memsegh = alloca(sizeof (picl_nodehdl_t) * TOTAL_MEM_SLOTS)) ==
96 	    NULL)
97 		return (PICL_FAILURE);
98 
99 	for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
100 		/*
101 		 * It means no segment for the slot if size is zero
102 		 */
103 		if (mmodinfo[i].size == 0) {
104 			memsegh[i] = NULL;
105 			continue;
106 		}
107 
108 		/*
109 		 * Create memory-segment node under memory
110 		 */
111 		err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT,
112 		    PICL_CLASS_MEMORY_SEGMENT, &msegh);
113 		if (err != PICL_SUCCESS)
114 			break;
115 
116 		/*
117 		 * For undo easily later
118 		 */
119 		memsegh[i] = msegh;
120 
121 		/*
122 		 * Add property, Size to memory-segment node
123 		 */
124 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
125 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ,
126 		    sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
127 		if (err != PICL_SUCCESS)
128 			break;
129 
130 		err = ptree_create_and_add_prop(msegh, &propinfo,
131 		    &mmodinfo[i].size, NULL);
132 		if (err != PICL_SUCCESS)
133 			break;
134 
135 		/*
136 		 * Add property, BaseAddress to memory-segment node
137 		 */
138 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
139 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ,
140 		    sizeof (mmodinfo[i].base), PICL_PROP_BASEADDRESS, NULL,
141 		    NULL);
142 		if (err != PICL_SUCCESS)
143 			break;
144 
145 		err = ptree_create_and_add_prop(msegh, &propinfo,
146 		    &mmodinfo[i].base, NULL);
147 		if (err != PICL_SUCCESS)
148 			break;
149 
150 		/*
151 		 * Add property, InterleaveFactor to memory-segment node
152 		 */
153 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
154 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (ifactor),
155 		    PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL);
156 		if (err != PICL_SUCCESS)
157 			break;
158 
159 		err = ptree_create_and_add_prop(msegh, &propinfo, &ifactor,
160 		    NULL);
161 		if (err != PICL_SUCCESS)
162 			break;
163 
164 		/*
165 		 * Add reference property to the memory module if memory
166 		 * module node handle is not NULL.
167 		 */
168 		if (mmodinfo[i].memmodh == NULL)
169 			continue;
170 
171 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
172 		    PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
173 		    PICL_REFPROP_MEMORY_MODULE, NULL, NULL);
174 		if (err != PICL_SUCCESS)
175 			break;
176 
177 		err = ptree_create_and_add_prop(msegh, &propinfo,
178 		    &mmodinfo[i].memmodh, NULL);
179 		if (err != PICL_SUCCESS)
180 			break;
181 	}
182 
183 	if (err != PICL_SUCCESS) {
184 		/*
185 		 * Undo in the logical memory tree
186 		 */
187 		for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
188 			if (memsegh[i] == NULL)
189 				continue;
190 
191 			(void) ptree_delete_node(memsegh[i]);
192 			(void) ptree_destroy_node(memsegh[i]);
193 		}
194 	}
195 
196 	return (err);
197 }
198 
199 /*
200  * Create physical memory tree
201  * memory-controller --- memory-module
202  */
203 static int
204 create_physical_tree(picl_nodehdl_t plfh, mmodinfo_t *mmodinfo)
205 {
206 	picl_nodehdl_t		mch, memmodh;
207 	ptree_propinfo_t	propinfo;
208 	int			i;
209 	int			err = PICL_SUCCESS;
210 	uint32_t		id;
211 
212 	/*
213 	 * Create memory-controller node under platform
214 	 */
215 	err = ptree_create_and_add_node(plfh, PICL_NAME_MEMORY_CONTROLLER,
216 	    PICL_CLASS_MEMORY_CONTROLLER, &mch);
217 	if (err != PICL_SUCCESS)
218 		return (err);
219 
220 	/*
221 	 * Create memory-module nodes and properties
222 	 * Get all memory modules with dimm
223 	 */
224 	for (i = 0; i < TOTAL_MEM_SLOTS; i++) {
225 		/*
226 		 * It means no dimm on the slot if size is zero
227 		 */
228 		if (mmodinfo[i].size == 0)
229 			continue;
230 
231 		/* Create memory-module node under memory-controller */
232 		err = ptree_create_and_add_node(mch, PICL_NAME_MEMORY_MODULE,
233 		    PICL_CLASS_MEMORY_MODULE, &memmodh);
234 		if (err != PICL_SUCCESS)
235 			break;
236 
237 		/*
238 		 * Update memory module node handle at mmodinfo
239 		 */
240 		mmodinfo[i].memmodh = memmodh;
241 
242 		/*
243 		 * Add property, Size to memory-module node
244 		 */
245 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
246 		    PICL_PTYPE_UNSIGNED_INT, PICL_READ,
247 		    sizeof (mmodinfo[i].size), PICL_PROP_SIZE, NULL, NULL);
248 		if (err != PICL_SUCCESS)
249 			break;
250 
251 		err = ptree_create_and_add_prop(memmodh, &propinfo,
252 		    &mmodinfo[i].size, NULL);
253 		if (err != PICL_SUCCESS)
254 			break;
255 
256 		/*
257 		 * Add property, ID to memory-module node
258 		 */
259 		err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
260 		    PICL_PTYPE_INT, PICL_READ, sizeof (id), PICL_PROP_ID,
261 		    NULL, NULL);
262 		if (err != PICL_SUCCESS)
263 			break;
264 
265 		id = i;
266 		err = ptree_create_and_add_prop(memmodh, &propinfo, &id, NULL);
267 		if (err != PICL_SUCCESS)
268 			break;
269 	}
270 
271 	if (err != PICL_SUCCESS) {
272 		/*
273 		 * Clear out the saved memory module node handle so that
274 		 * logical memory tree won't link to memory module.
275 		 */
276 		for (i = 0; i < TOTAL_MEM_SLOTS; i++)
277 			mmodinfo[i].memmodh = NULL;
278 
279 		/*
280 		 * Undo in the physical memory tree
281 		 */
282 		(void) ptree_delete_node(mch);
283 		(void) ptree_destroy_node(mch);
284 	}
285 
286 	return (err);
287 }
288 
289 /*
290  * Get the memory module and memory segment information from
291  * property reg of memory node.
292  *
293  * mmodinfo will be updated. Also, the pointers to mseginfo and
294  * the number of segments will be passed to the caller.
295  */
296 static int
297 get_reg_info(picl_nodehdl_t plfh, picl_nodehdl_t memh,
298     mmodinfo_t *mmodinfo)
299 {
300 	picl_prophdl_t		proph;
301 	ptree_propinfo_t	pinfo;
302 	regspec_t		*memspec;
303 	int			i, err;
304 	int			pval;
305 	int			nregspec;
306 
307 
308 	/*
309 	 * Check if the #size-cells of the platform node is 2
310 	 */
311 	err = ptree_get_propval_by_name(plfh, OBP_PROP_SIZE_CELLS, &pval,
312 	    sizeof (pval));
313 
314 	if (err == PICL_PROPNOTFOUND)
315 		pval = SUPPORTED_NUM_CELL_SIZE;
316 	else if (err != PICL_SUCCESS)
317 		return (err);
318 
319 	/*
320 	 * don't know to handle other vals
321 	 */
322 	if (pval != SUPPORTED_NUM_CELL_SIZE)
323 		return (PICL_FAILURE);
324 
325 	/*
326 	 * Get property reg of memory node
327 	 */
328 	err = ptree_get_prop_by_name(memh, OBP_REG, &proph);
329 	if (err != PICL_SUCCESS)
330 		return (err);
331 
332 	err = ptree_get_propinfo(proph, &pinfo);
333 	if (err != PICL_SUCCESS)
334 		return (err);
335 
336 	if ((memspec = alloca(pinfo.piclinfo.size)) == NULL)
337 		return (PICL_FAILURE);
338 
339 	nregspec = pinfo.piclinfo.size / sizeof (*memspec);
340 
341 	if ((nregspec == 0) || (nregspec > TOTAL_MEM_SLOTS))
342 		return (PICL_FAILURE);
343 
344 	err = ptree_get_propval(proph, memspec, pinfo.piclinfo.size);
345 	if (err != PICL_SUCCESS)
346 		return (err);
347 
348 
349 	for (i = 0; i < nregspec; i++) {
350 
351 		mmodinfo[i].base = memspec[i].physaddr;
352 		mmodinfo[i].size = memspec[i].size;
353 
354 	}
355 
356 	return (PICL_SUCCESS);
357 }
358 
359 /*
360  * executed as part of .init when the plugin is dlopen()ed
361  */
362 static void
363 piclmemcfg_register(void)
364 {
365 	(void) picld_plugin_register(&my_reg_info);
366 }
367 
368 /*
369  * Init entry point of the plugin
370  * Creates the PICL nodes and properties in the physical and logical aspects.
371  */
372 static void
373 piclmemcfg_init(void)
374 {
375 	picl_nodehdl_t		plfh, memh;
376 	mmodinfo_t		mmodinfo[TOTAL_MEM_SLOTS];
377 
378 	/*
379 	 * Get platform node
380 	 */
381 	if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) {
382 		syslog(LOG_ERR, EM_INIT_FAILED);
383 		return;
384 	}
385 
386 	/*
387 	 * Find the memory node
388 	 */
389 	if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) {
390 		syslog(LOG_ERR, EM_INIT_FAILED);
391 		return;
392 	}
393 
394 	/*
395 	 * Initialize the mmodinfo and get segment information from reg
396 	 */
397 	(void) memset(mmodinfo, 0, sizeof (mmodinfo));
398 
399 	if ((get_reg_info(plfh, memh, mmodinfo)) != PICL_SUCCESS) {
400 		syslog(LOG_ERR, EM_INIT_FAILED);
401 		return;
402 	}
403 
404 	/*
405 	 * Create subtree of memory-controller in the physical aspect.
406 	 * memory-controller --- memory-module
407 	 */
408 	if ((create_physical_tree(plfh, mmodinfo)) != PICL_SUCCESS)
409 		syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED);
410 
411 	/*
412 	 * Create subtree of memory in the logical aspect.
413 	 * memory --- memory-segment
414 	 */
415 	if ((create_logical_tree(memh, mmodinfo)) != PICL_SUCCESS)
416 		syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED);
417 }
418 
419 /*
420  * fini entry point of the plugin
421  */
422 static void
423 piclmemcfg_fini(void)
424 {
425 }
426