cmd: remove sparc-only virtinfo
[unleashed.git] / usr / src / cmd / picl / plugins / sun4v / pri / mem_prop_update.c
blobc27a38f69856aedf9ef6a4104552ea988e313a35
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * The PRI plug-in picks up memory configuration data from the PRI
28 * and injects this into PICL's /platform tree. It only populates
29 * the logical view of memory: memory, memory-segment, memory-bank.
30 * It does not populate the /device tree since there are no memory
31 * controller devices on sun4v.
34 #include "priplugin.h"
35 #include "../../common/memcfg/piclmemcfg.h"
37 static void
38 add_memory_props(picl_nodehdl_t node, mde_cookie_t memorylistp, md_t *mdp,
39 uint64_t size);
41 static void
42 add_bank_props(picl_nodehdl_t node, mde_cookie_t banklistp,
43 md_t *mdp, uint64_t *size, uint64_t *mask, unsigned int id);
44 static uint64_t countbits(uint64_t v);
46 static void
47 add_segment_props(picl_nodehdl_t node, mde_cookie_t segmentlistp,
48 md_t *mdp, uint64_t interleave, uint64_t *size, uint64_t base);
51 * Callback function for picl_walk_tree_by_class().
52 * NOTE: picl_walk_tree_by_class() maps the return codes PICL_WALK_CONTINUE
53 * and PICL_WALK_TERMINATE to PICL_SUCCESS.
55 int
56 add_mem_prop(picl_nodehdl_t node, void *args)
58 mde_cookie_t *memorylistp, *segmentlistp, *banklistp;
59 picl_prophdl_t memh, segmenth, bankh;
60 mde_cookie_t *buf, md_rootnode;
61 int j, k, num_nodes, interleave, err;
62 int nsegments, nbanks, nmemory;
63 uint64_t memsize, segsize, segbase;
64 uint64_t size, mask;
65 md_t *mdp = (md_t *)args;
67 if (mdp == NULL)
68 return (PICL_WALK_CONTINUE);
70 md_rootnode = md_root_node(mdp);
73 * An absence of nodes or failure to obtain memory for searches
74 * or absence of the /memory node will cause this to fail.
75 * Return PICL_WALK_SUCCESS to allow the plug-in to continue.
77 num_nodes = md_node_count(mdp);
78 if (num_nodes == 0) {
79 pri_debug(LOG_NOTICE, "add_mem_prop: no nodes to walk\n");
80 return (PICL_SUCCESS);
82 buf = (mde_cookie_t *)malloc(sizeof (mde_cookie_t) * num_nodes * 3);
83 if (buf == NULL) {
84 pri_debug(LOG_NOTICE, "add_mem_prop: can't allocate memory\n");
85 return (PICL_SUCCESS);
88 memorylistp = &buf[0];
89 segmentlistp = &buf[num_nodes];
90 banklistp = &buf[num_nodes * 2];
92 if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) {
93 pri_debug(LOG_NOTICE,
94 "add_mem_prop: can't find /memory node in platform tree\n");
95 free(buf);
96 return (PICL_SUCCESS);
100 * There should be only one memory node.
101 * If we can't find what we're looking for in the DAG then
102 * return PICL_PROPNOTFOUND to get the caller to re-try with
103 * a different property name.
105 nmemory = md_scan_dag(mdp, md_rootnode, md_find_name(mdp,
106 "memory-segments"), md_find_name(mdp, "fwd"), memorylistp);
107 if (nmemory != 1) {
108 pri_debug(LOG_NOTICE,
109 "add_mem_prop: wrong number of memory dags: expected "
110 "1, got %d\n", nmemory);
111 free(buf);
112 return (PICL_PROPNOTFOUND);
115 nsegments = md_scan_dag(mdp, memorylistp[0],
116 md_find_name(mdp, "memory-segment"),
117 md_find_name(mdp, "fwd"),
118 segmentlistp);
120 if (nsegments == 0) {
121 pri_debug(LOG_NOTICE, "add_mem_prop: wrong number of memory "
122 "segments: expected >0, got %d\n", nsegments);
123 free(buf);
124 return (PICL_PROPNOTFOUND);
128 * Add memory segments, keep running total of system memory.
130 for (memsize = 0, segsize = 0, j = 0; j < nsegments;
131 ++j, memsize += segsize) {
132 nbanks = 0;
133 err = ptree_create_and_add_node(memh,
134 PICL_NAME_MEMORY_SEGMENT,
135 PICL_CLASS_MEMORY_SEGMENT, &segmenth);
136 if (err == PICL_SUCCESS) {
137 size = 0;
138 mask = 0;
141 * Need to pull this out here since it's used for
142 * the ID.
144 if (md_get_prop_val(mdp, segmentlistp[j], "base",
145 &segbase))
146 segbase = 0ULL;
149 * Add banks under each segment.
151 nbanks = md_scan_dag(mdp, segmentlistp[j],
152 md_find_name(mdp, "memory-bank"),
153 md_find_name(mdp, "fwd"),
154 banklistp);
156 if (nbanks <= 0) {
157 pri_debug(LOG_NOTICE, "add_mem_prop: no banks "
158 "found for segment %d\n", j);
159 } else {
160 for (k = 0; k < nbanks; ++k) {
161 err =
162 ptree_create_and_add_node(segmenth,
163 PICL_NAME_MEMORY_BANK,
164 PICL_CLASS_MEMORY_BANK, &bankh);
165 if (err == PICL_SUCCESS) {
167 * Add AddressMatch,
168 * AddressMask, Size, and
169 * ID to each bank.
171 add_bank_props(bankh,
172 banklistp[k],
173 mdp,
174 &size, &mask,
175 (segbase >> 32) * j + k);
182 * Add Interleave, BaseAddress, and Size to each segment.
184 interleave = 2 << (countbits(mask & (size - 1)) - 1);
185 add_segment_props(segmenth, segmentlistp[j],
186 mdp, interleave, &segsize, segbase);
190 * Add TransferSize and Size (total memory) to this node.
192 add_memory_props(memh, memorylistp[0], mdp, memsize);
194 free(buf);
195 return (PICL_WALK_CONTINUE);
198 static void
199 add_bank_props(picl_nodehdl_t bankh, mde_cookie_t banklistp,
200 md_t *mdp, uint64_t *size, uint64_t *mask, unsigned int id)
202 uint64_t int_value;
203 mde_cookie_t *dimmlistp;
204 int node_count, i, type_size, nac_size, status;
205 uint8_t *type;
206 char *pc, *nac;
207 picl_prophdl_t dimmh;
209 *size = 0ULL;
210 *mask = 0ULL;
212 node_count = md_node_count(mdp);
213 dimmlistp = (mde_cookie_t *)malloc(node_count * sizeof (mde_cookie_t));
214 if (dimmlistp == NULL) {
215 pri_debug(LOG_NOTICE,
216 "add_bank_props: can't allocate memory\n");
217 return;
220 if (!md_get_prop_val(mdp, banklistp, "size", &int_value)) {
221 add_md_prop(bankh, sizeof (int_value), PICL_PROP_SIZE,
222 &int_value, PICL_PTYPE_UNSIGNED_INT);
223 *size = int_value;
225 if (!md_get_prop_val(mdp, banklistp, "mask",
226 &int_value)) {
227 add_md_prop(bankh, sizeof (int_value),
228 PICL_PROP_ADDRESSMASK,
229 &int_value, PICL_PTYPE_UNSIGNED_INT);
230 *mask = int_value;
232 if (!md_get_prop_val(mdp, banklistp, "match",
233 &int_value)) {
234 add_md_prop(bankh, sizeof (int_value),
235 PICL_PROP_ADDRESSMATCH,
236 &int_value, PICL_PTYPE_UNSIGNED_INT);
239 add_md_prop(bankh, sizeof (id), PICL_PROP_ID, &id,
240 PICL_PTYPE_INT);
242 node_count = md_scan_dag(mdp, banklistp, md_find_name(mdp, "component"),
243 md_find_name(mdp, "fwd"), dimmlistp);
245 for (i = 0; i < node_count; ++i) {
246 status = md_get_prop_str(mdp, dimmlistp[i], "type",
247 (char **)&type);
248 if (status == -1) {
249 status = md_get_prop_data(mdp, dimmlistp[i],
250 "type", &type, &type_size);
252 if (status == -1) /* can't get node type - just skip */
253 continue;
254 if (strcmp((const char *)type, "dimm") == 0) {
255 if (md_get_prop_str(mdp, dimmlistp[i], "nac",
256 (char **)&nac) == 0) {
257 nac_size = strlen(nac) + 1;
258 if (ptree_create_and_add_node(bankh,
259 PICL_NAME_MEMORY_MODULE,
260 PICL_CLASS_MEMORY_MODULE, &dimmh) ==
261 PICL_SUCCESS) {
262 add_md_prop(dimmh, nac_size,
263 "nac", nac,
264 PICL_PTYPE_CHARSTRING);
265 if ((pc = strrchr(nac, '/')) != NULL)
266 nac = ++pc;
267 nac_size = strlen(nac) + 1;
268 add_md_prop(dimmh, nac_size,
269 PICL_PROP_LABEL, nac,
270 PICL_PTYPE_CHARSTRING);
275 free(dimmlistp);
278 static uint64_t
279 countbits(uint64_t v)
281 uint64_t c; /* c accumulates the total bits set in v */
283 for (c = 0; v; c++)
284 v &= v - 1; /* clear the least significant bit set */
285 return (c);
288 static void
289 add_segment_props(picl_nodehdl_t node, mde_cookie_t segmentlistp,
290 md_t *mdp, uint64_t interleave, uint64_t *size, uint64_t base)
292 uint64_t int_value;
294 *size = 0;
295 if (!md_get_prop_val(mdp, segmentlistp, "size", &int_value)) {
296 add_md_prop(node, sizeof (int_value),
297 PICL_PROP_SIZE, &int_value,
298 PICL_PTYPE_UNSIGNED_INT);
299 *size = int_value;
301 add_md_prop(node, sizeof (base), PICL_PROP_BASEADDRESS,
302 &base, PICL_PTYPE_UNSIGNED_INT);
304 add_md_prop(node, sizeof (interleave), PICL_PROP_INTERLEAVE_FACTOR,
305 &interleave, PICL_PTYPE_UNSIGNED_INT);
308 static void
309 add_memory_props(picl_nodehdl_t node, mde_cookie_t memorylistp, md_t *mdp,
310 uint64_t size)
312 uint64_t int_value;
315 * If the top-level node has a size property then use that,
316 * otherwise use the size that was calculated by the caller
317 * and passed in.
319 if (md_get_prop_val(mdp, memorylistp, "size", &int_value))
320 int_value = size;
321 add_md_prop(node, sizeof (int_value), PICL_PROP_SIZE, &int_value,
322 PICL_PTYPE_UNSIGNED_INT);
323 if (!md_get_prop_val(mdp, memorylistp, "transfer_size",
324 &int_value)) {
325 add_md_prop(node, sizeof (int_value),
326 PICL_PROP_TRANSFER_SIZE,
327 &int_value, PICL_PTYPE_UNSIGNED_INT);