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.
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"
38 add_memory_props(picl_nodehdl_t node
, mde_cookie_t memorylistp
, md_t
*mdp
,
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
);
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.
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
;
65 md_t
*mdp
= (md_t
*)args
;
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
);
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);
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
) {
94 "add_mem_prop: can't find /memory node in platform tree\n");
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
);
108 pri_debug(LOG_NOTICE
,
109 "add_mem_prop: wrong number of memory dags: expected "
110 "1, got %d\n", nmemory
);
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"),
120 if (nsegments
== 0) {
121 pri_debug(LOG_NOTICE
, "add_mem_prop: wrong number of memory "
122 "segments: expected >0, got %d\n", nsegments
);
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
) {
133 err
= ptree_create_and_add_node(memh
,
134 PICL_NAME_MEMORY_SEGMENT
,
135 PICL_CLASS_MEMORY_SEGMENT
, &segmenth
);
136 if (err
== PICL_SUCCESS
) {
141 * Need to pull this out here since it's used for
144 if (md_get_prop_val(mdp
, segmentlistp
[j
], "base",
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"),
157 pri_debug(LOG_NOTICE
, "add_mem_prop: no banks "
158 "found for segment %d\n", j
);
160 for (k
= 0; k
< nbanks
; ++k
) {
162 ptree_create_and_add_node(segmenth
,
163 PICL_NAME_MEMORY_BANK
,
164 PICL_CLASS_MEMORY_BANK
, &bankh
);
165 if (err
== PICL_SUCCESS
) {
168 * AddressMask, Size, and
171 add_bank_props(bankh
,
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
);
195 return (PICL_WALK_CONTINUE
);
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
)
203 mde_cookie_t
*dimmlistp
;
204 int node_count
, i
, type_size
, nac_size
, status
;
207 picl_prophdl_t dimmh
;
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");
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
);
225 if (!md_get_prop_val(mdp
, banklistp
, "mask",
227 add_md_prop(bankh
, sizeof (int_value
),
228 PICL_PROP_ADDRESSMASK
,
229 &int_value
, PICL_PTYPE_UNSIGNED_INT
);
232 if (!md_get_prop_val(mdp
, banklistp
, "match",
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
,
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",
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 */
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
) ==
262 add_md_prop(dimmh
, nac_size
,
264 PICL_PTYPE_CHARSTRING
);
265 if ((pc
= strrchr(nac
, '/')) != NULL
)
267 nac_size
= strlen(nac
) + 1;
268 add_md_prop(dimmh
, nac_size
,
269 PICL_PROP_LABEL
, nac
,
270 PICL_PTYPE_CHARSTRING
);
279 countbits(uint64_t v
)
281 uint64_t c
; /* c accumulates the total bits set in v */
284 v
&= v
- 1; /* clear the least significant bit set */
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
)
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
);
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
);
309 add_memory_props(picl_nodehdl_t node
, mde_cookie_t memorylistp
, md_t
*mdp
,
315 * If the top-level node has a size property then use that,
316 * otherwise use the size that was calculated by the caller
319 if (md_get_prop_val(mdp
, memorylistp
, "size", &int_value
))
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",
325 add_md_prop(node
, sizeof (int_value
),
326 PICL_PROP_TRANSFER_SIZE
,
327 &int_value
, PICL_PTYPE_UNSIGNED_INT
);